diff options
-rw-r--r-- | apps/debug_menu.c | 62 | ||||
-rw-r--r-- | apps/lang/english.lang | 4 | ||||
-rw-r--r-- | apps/main_menu.c | 12 | ||||
-rw-r--r-- | firmware/powermgmt.c | 150 | ||||
-rw-r--r-- | firmware/powermgmt.h | 17 |
5 files changed, 204 insertions, 41 deletions
diff --git a/apps/debug_menu.c b/apps/debug_menu.c index 3aca2b8f2c..772e93229f 100644 --- a/apps/debug_menu.c +++ b/apps/debug_menu.c | |||
@@ -78,9 +78,8 @@ bool dbg_os(void) | |||
78 | } | 78 | } |
79 | 79 | ||
80 | lcd_update(); | 80 | lcd_update(); |
81 | sleep(HZ/10); | ||
82 | 81 | ||
83 | button = button_get(false); | 82 | button = button_get_w_tmo(HZ/10); |
84 | 83 | ||
85 | switch(button) | 84 | switch(button) |
86 | { | 85 | { |
@@ -112,9 +111,7 @@ bool dbg_os(void) | |||
112 | snprintf(buf, 32, "%d: %d%% ", currval, usage); | 111 | snprintf(buf, 32, "%d: %d%% ", currval, usage); |
113 | lcd_puts(0, 1, buf); | 112 | lcd_puts(0, 1, buf); |
114 | 113 | ||
115 | sleep(HZ/10); | 114 | button = button_get_w_tmo(HZ/10); |
116 | |||
117 | button = button_get(false); | ||
118 | 115 | ||
119 | switch(button) | 116 | switch(button) |
120 | { | 117 | { |
@@ -333,7 +330,7 @@ bool dbg_partitions(void) | |||
333 | lcd_puts(0, 0, "Partition"); | 330 | lcd_puts(0, 0, "Partition"); |
334 | lcd_puts(0, 1, "list"); | 331 | lcd_puts(0, 1, "list"); |
335 | lcd_update(); | 332 | lcd_update(); |
336 | sleep(HZ); | 333 | sleep(HZ/2); |
337 | 334 | ||
338 | while(1) | 335 | while(1) |
339 | { | 336 | { |
@@ -431,9 +428,7 @@ bool dbg_ports(void) | |||
431 | lcd_puts(0, 7, buf); | 428 | lcd_puts(0, 7, buf); |
432 | 429 | ||
433 | lcd_update(); | 430 | lcd_update(); |
434 | sleep(HZ/10); | 431 | button = button_get(HZ/10); |
435 | |||
436 | button = button_get(false); | ||
437 | 432 | ||
438 | switch(button) | 433 | switch(button) |
439 | { | 434 | { |
@@ -513,9 +508,7 @@ bool dbg_ports(void) | |||
513 | snprintf(buf, 32, "Batt: %d.%02dV", batt_int, batt_frac); | 508 | snprintf(buf, 32, "Batt: %d.%02dV", batt_int, batt_frac); |
514 | lcd_puts(0, 1, buf); | 509 | lcd_puts(0, 1, buf); |
515 | 510 | ||
516 | sleep(HZ/5); | 511 | button = button_get_w_tmo(HZ/5); |
517 | |||
518 | button = button_get(false); | ||
519 | 512 | ||
520 | switch(button) | 513 | switch(button) |
521 | { | 514 | { |
@@ -566,9 +559,8 @@ bool dbg_rtc(void) | |||
566 | } | 559 | } |
567 | 560 | ||
568 | lcd_update(); | 561 | lcd_update(); |
569 | sleep(HZ/2); | ||
570 | 562 | ||
571 | button = button_get(false); | 563 | button = button_get_w_tmo(HZ/2); |
572 | 564 | ||
573 | switch(button) | 565 | switch(button) |
574 | { | 566 | { |
@@ -623,9 +615,8 @@ bool dbg_mas(void) | |||
623 | } | 615 | } |
624 | 616 | ||
625 | lcd_update(); | 617 | lcd_update(); |
626 | sleep(HZ/16); | ||
627 | 618 | ||
628 | switch(button_get(false)) | 619 | switch(button_get_w_tmo(HZ/16)) |
629 | { | 620 | { |
630 | #ifdef HAVE_RECORDER_KEYPAD | 621 | #ifdef HAVE_RECORDER_KEYPAD |
631 | case BUTTON_DOWN: | 622 | case BUTTON_DOWN: |
@@ -674,9 +665,8 @@ bool dbg_mas_codec(void) | |||
674 | } | 665 | } |
675 | 666 | ||
676 | lcd_update(); | 667 | lcd_update(); |
677 | sleep(HZ/16); | ||
678 | 668 | ||
679 | switch(button_get(false)) | 669 | switch(button_get_w_tmo(HZ/16)) |
680 | { | 670 | { |
681 | case BUTTON_DOWN: | 671 | case BUTTON_DOWN: |
682 | addr += 4; | 672 | addr += 4; |
@@ -805,12 +795,42 @@ bool view_battery(void) | |||
805 | lcd_puts(0, i+1, buf); | 795 | lcd_puts(0, i+1, buf); |
806 | } | 796 | } |
807 | break; | 797 | break; |
798 | |||
799 | case 3: /* remeining time estimation: */ | ||
800 | lcd_clear_display(); | ||
801 | lcd_puts(0, 0, "Remaining time:"); | ||
802 | |||
803 | snprintf(buf, 30, "Cycle time: %d m", powermgmt_last_cycle_startstop_min); | ||
804 | lcd_puts(0, 1, buf); | ||
805 | |||
806 | snprintf(buf, 30, "Lev.at cycle start: %d%%", powermgmt_last_cycle_level); | ||
807 | lcd_puts(0, 2, buf); | ||
808 | |||
809 | snprintf(buf, 30, "Last PwrHist val: %d.%02d V", | ||
810 | power_history[POWER_HISTORY_LEN-1] / 100, | ||
811 | power_history[POWER_HISTORY_LEN-1] % 100); | ||
812 | lcd_puts(0, 3, buf); | ||
813 | |||
814 | snprintf(buf, 30, "Lazy time amount: %d%%", | ||
815 | (powermgmt_last_cycle_startstop_min < 20) | ||
816 | ? battery_lazyness[powermgmt_last_cycle_startstop_min] | ||
817 | : 0); | ||
818 | lcd_puts(0, 4, buf); | ||
819 | |||
820 | snprintf(buf, 30, "resulting act.lev: %d%%", battery_level()); | ||
821 | lcd_puts(0, 5, buf); | ||
822 | |||
823 | snprintf(buf, 30, "Est. remaining: %d m", powermgmt_est_runningtime_min); | ||
824 | lcd_puts(0, 6, buf); | ||
825 | |||
826 | #ifdef HAVE_CHARGE_CTRL | ||
827 | #endif | ||
828 | break; | ||
808 | } | 829 | } |
809 | 830 | ||
810 | lcd_update(); | 831 | lcd_update(); |
811 | sleep(HZ/2); | ||
812 | 832 | ||
813 | switch(button_get(false)) | 833 | switch(button_get_w_tmo(HZ/2)) |
814 | { | 834 | { |
815 | case BUTTON_UP: | 835 | case BUTTON_UP: |
816 | if (view) | 836 | if (view) |
@@ -818,7 +838,7 @@ bool view_battery(void) | |||
818 | break; | 838 | break; |
819 | 839 | ||
820 | case BUTTON_DOWN: | 840 | case BUTTON_DOWN: |
821 | if (view < 2) | 841 | if (view < 3) |
822 | view++; | 842 | view++; |
823 | break; | 843 | break; |
824 | 844 | ||
diff --git a/apps/lang/english.lang b/apps/lang/english.lang index 82d22a7c7f..45270293f5 100644 --- a/apps/lang/english.lang +++ b/apps/lang/english.lang | |||
@@ -1162,3 +1162,7 @@ desc: show only playlist | |||
1162 | eng: "Playlists" | 1162 | eng: "Playlists" |
1163 | new: | 1163 | new: |
1164 | 1164 | ||
1165 | id: LANG_BATTERY_TIME | ||
1166 | desc: battery level in % and estimated time remaining | ||
1167 | eng: "%d%% %dh %dm" | ||
1168 | new: | ||
diff --git a/apps/main_menu.c b/apps/main_menu.c index 49ad9c9f5b..a5517f928d 100644 --- a/apps/main_menu.c +++ b/apps/main_menu.c | |||
@@ -183,21 +183,13 @@ bool show_info(void) | |||
183 | #endif | 183 | #endif |
184 | lcd_puts(0, y++, s); | 184 | lcd_puts(0, y++, s); |
185 | 185 | ||
186 | #ifdef HAVE_LCD_CHARCELLS | ||
187 | snprintf(s, sizeof(s), str(LANG_BATTERY_LEVEL_PLAYER), | ||
188 | battery_level(), battery_level_safe() ? "" : "!"); | ||
189 | #else | ||
190 | #ifdef HAVE_CHARGE_CTRL | 186 | #ifdef HAVE_CHARGE_CTRL |
191 | if (charger_enabled) | 187 | if (charger_enabled) |
192 | snprintf(s, sizeof(s), str(LANG_BATTERY_CHARGE)); | 188 | snprintf(s, sizeof(s), str(LANG_BATTERY_CHARGE)); |
193 | else | 189 | else |
194 | snprintf(s, sizeof(s), str(LANG_BATTERY_LEVEL_RECORDER), | ||
195 | battery_level(), battery_level_safe() ? "" : " !!"); | ||
196 | #else | ||
197 | snprintf(s, sizeof(s), str(LANG_BATTERY_LEVEL_RECORDER), | ||
198 | battery_level(), battery_level_safe() ? "" : " !!"); | ||
199 | #endif | ||
200 | #endif | 190 | #endif |
191 | snprintf(s, sizeof(s), str(LANG_BATTERY_TIME), battery_level(), | ||
192 | battery_time() / 60, battery_time() % 60); | ||
201 | lcd_puts(0, y++, s); | 193 | lcd_puts(0, y++, s); |
202 | } | 194 | } |
203 | 195 | ||
diff --git a/firmware/powermgmt.c b/firmware/powermgmt.c index 93d3192904..0db751161c 100644 --- a/firmware/powermgmt.c +++ b/firmware/powermgmt.c | |||
@@ -41,6 +41,11 @@ int battery_level(void) | |||
41 | return 100; | 41 | return 100; |
42 | } | 42 | } |
43 | 43 | ||
44 | int battery_time(void) | ||
45 | { | ||
46 | return 500; | ||
47 | } | ||
48 | |||
44 | bool battery_level_safe(void) | 49 | bool battery_level_safe(void) |
45 | { | 50 | { |
46 | return true; | 51 | return true; |
@@ -58,18 +63,62 @@ static int poweroff_idle_timeout_value[15] = | |||
58 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 30, 45, 60 | 63 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 30, 45, 60 |
59 | }; | 64 | }; |
60 | 65 | ||
66 | static int percent_to_volt_nocharge[11] = /* voltages (centivolt) of 0%, 10%, ... 100% when charging disabled */ | ||
67 | { | ||
68 | 450, 481, 491, 497, 503, 507, 512, 514, 517, 528, 560 | ||
69 | }; | ||
70 | |||
71 | static int percent_to_volt_charge[11] = /* voltages (centivolt) of 0%, 10%, ... 100% when charging enabled */ | ||
72 | { | ||
73 | 476, 544, 551, 556, 561, 564, 566, 576, 582, 584, 585 | ||
74 | }; | ||
75 | |||
76 | int battery_lazyness[20] = /* how does the battery react when plugging in/out the charger */ | ||
77 | { | ||
78 | 0, 17, 31, 42, 52, 60, 67, 72, 77, 81, 84, 87, 89, 91, 92, 94, 95, 95, 96, 97 | ||
79 | }; | ||
80 | |||
61 | static char power_stack[DEFAULT_STACK_SIZE]; | 81 | static char power_stack[DEFAULT_STACK_SIZE]; |
62 | static char power_thread_name[] = "power"; | 82 | static char power_thread_name[] = "power"; |
63 | 83 | ||
64 | static int poweroff_timeout = 0; | 84 | static int poweroff_timeout = 0; |
65 | static long last_charge_time = 0; | 85 | static long last_charge_time = 0; |
86 | static int powermgmt_est_runningtime_min = -1; | ||
66 | 87 | ||
67 | unsigned short power_history[POWER_HISTORY_LEN]; | 88 | unsigned short power_history[POWER_HISTORY_LEN]; |
68 | #ifdef HAVE_CHARGE_CTRL | 89 | #ifdef HAVE_CHARGE_CTRL |
69 | char power_message[POWER_MESSAGE_LEN] = ""; | 90 | char power_message[POWER_MESSAGE_LEN] = ""; |
70 | char charge_restart_level = CHARGE_RESTART_HI; | 91 | char charge_restart_level = CHARGE_RESTART_HI; |
92 | |||
93 | int powermgmt_last_cycle_startstop_min = 20; /* how many minutes ago was the charging started or stopped? */ | ||
94 | int powermgmt_last_cycle_level = 0; /* which level had the batteries at this time? */ | ||
71 | #endif | 95 | #endif |
72 | 96 | ||
97 | |||
98 | int battery_time(void) | ||
99 | { | ||
100 | return powermgmt_est_runningtime_min; | ||
101 | } | ||
102 | |||
103 | /* look into the percent_to_volt_* table and get a realistic battery level percentage */ | ||
104 | int voltage_to_percent(int voltage, int* table) | ||
105 | { | ||
106 | if (voltage <= table[0]) | ||
107 | return 0; | ||
108 | else | ||
109 | if (voltage >= table[10]) | ||
110 | return 100; | ||
111 | else { | ||
112 | /* search nearest value */ | ||
113 | int i = 0; | ||
114 | while ((i < 10) && (table[i+1] < voltage)) | ||
115 | i++; | ||
116 | /* interpolate linear between the smaller and greater value */ | ||
117 | return i * 10 /* 10th */ | ||
118 | + (voltage - table[i]) * 10 / (table[i+1] - table[i]); /* 1th */ | ||
119 | } | ||
120 | } | ||
121 | |||
73 | /* Returns battery level in percent */ | 122 | /* Returns battery level in percent */ |
74 | int battery_level(void) | 123 | int battery_level(void) |
75 | { | 124 | { |
@@ -95,7 +144,33 @@ int battery_level(void) | |||
95 | if(level < BATTERY_LEVEL_EMPTY) | 144 | if(level < BATTERY_LEVEL_EMPTY) |
96 | level = BATTERY_LEVEL_EMPTY; | 145 | level = BATTERY_LEVEL_EMPTY; |
97 | 146 | ||
98 | return ((level-BATTERY_LEVEL_EMPTY) * 100) / BATTERY_RANGE; | 147 | /* level now stores the voltage in centivolts */ |
148 | /* let's calculate a percentage now with using the voltage arrays */ | ||
149 | |||
150 | #ifdef HAVE_CHARGE_CTRL | ||
151 | if (powermgmt_last_cycle_startstop_min < 20) { | ||
152 | /* the batteries are lazy, so take a value between the result of the two table lookups */ | ||
153 | if (charger_enabled) | ||
154 | level = (voltage_to_percent(level, percent_to_volt_charge) | ||
155 | * battery_lazyness[powermgmt_last_cycle_startstop_min] | ||
156 | + voltage_to_percent(level, percent_to_volt_nocharge) | ||
157 | * (100 - battery_lazyness[powermgmt_last_cycle_startstop_min])) / 100; | ||
158 | else | ||
159 | level = (voltage_to_percent(level, percent_to_volt_nocharge) | ||
160 | * battery_lazyness[powermgmt_last_cycle_startstop_min] | ||
161 | + voltage_to_percent(level, percent_to_volt_charge) | ||
162 | * (100 - battery_lazyness[powermgmt_last_cycle_startstop_min])) / 100; | ||
163 | } else { | ||
164 | if (charger_enabled) | ||
165 | level = voltage_to_percent(level, percent_to_volt_charge); | ||
166 | else | ||
167 | level = voltage_to_percent(level, percent_to_volt_nocharge); | ||
168 | } | ||
169 | #else | ||
170 | level = voltage_to_percent(level, percent_to_volt_nocharge); /* always use the nocharge table */ | ||
171 | #endif | ||
172 | |||
173 | return level; | ||
99 | } | 174 | } |
100 | 175 | ||
101 | /* Tells if the battery level is safe for disk writes */ | 176 | /* Tells if the battery level is safe for disk writes */ |
@@ -180,6 +255,8 @@ static void power_thread(void) | |||
180 | #ifdef HAVE_CHARGE_CTRL | 255 | #ifdef HAVE_CHARGE_CTRL |
181 | int delta; | 256 | int delta; |
182 | int charged_time = 0; | 257 | int charged_time = 0; |
258 | int charge_max_time_now = 0; | ||
259 | int charge_pause = 0; /* no charging pause at the beginning */ | ||
183 | #endif | 260 | #endif |
184 | 261 | ||
185 | while (1) | 262 | while (1) |
@@ -215,18 +292,43 @@ static void power_thread(void) | |||
215 | /* insert new value in the end, in centivolts 8-) */ | 292 | /* insert new value in the end, in centivolts 8-) */ |
216 | power_history[POWER_HISTORY_LEN-1] = (avg * BATTERY_SCALE_FACTOR) / 10000; | 293 | power_history[POWER_HISTORY_LEN-1] = (avg * BATTERY_SCALE_FACTOR) / 10000; |
217 | 294 | ||
295 | /* calculate estimated remaining running time */ | ||
296 | /* not charging: remaining running time */ | ||
297 | /* charging: remaining charging time */ | ||
298 | #ifdef HAVE_CHARGE_CTRL | ||
299 | if (charger_enabled) | ||
300 | /* if taking the nocharge battery level, charging lasts 30% longer than the value says */ | ||
301 | /* so consider it because there's the battery lazyness inside the the battery_level */ | ||
302 | if (powermgmt_last_cycle_startstop_min < 20) { | ||
303 | i = (100 - battery_lazyness[powermgmt_last_cycle_startstop_min]) * 30 / 100 ; /* 0..30 */ | ||
304 | powermgmt_est_runningtime_min = (100 - battery_level()) * BATTERY_CAPACITY / 100 * (100 + i) / 100 * 60 / CURRENT_CHARGING; | ||
305 | } else { | ||
306 | powermgmt_est_runningtime_min = (100 - battery_level()) * BATTERY_CAPACITY / 100 * 60 / CURRENT_CHARGING; | ||
307 | } | ||
308 | else | ||
309 | #endif | ||
310 | powermgmt_est_runningtime_min = battery_level() * BATTERY_CAPACITY / 100 * 60 / CURRENT_NORMAL; | ||
311 | |||
218 | #ifdef HAVE_CHARGE_CTRL | 312 | #ifdef HAVE_CHARGE_CTRL |
313 | |||
314 | if (charge_pause > 0) | ||
315 | charge_pause--; | ||
316 | |||
219 | if (charger_inserted()) { | 317 | if (charger_inserted()) { |
220 | if (charger_enabled) { | 318 | if (charger_enabled) { |
221 | /* charger inserted and enabled */ | 319 | /* charger inserted and enabled */ |
222 | charged_time++; | 320 | charged_time++; |
223 | if (charged_time > CHARGE_MAX_TIME) { | 321 | snprintf(power_message, POWER_MESSAGE_LEN, "Chg %dm max %dm", charged_time, charge_max_time_now); |
224 | DEBUGF("power: charged_time > CHARGE_MAX_TIME, enough!\n"); | 322 | |
323 | if (charged_time > charge_max_time_now) { | ||
324 | DEBUGF("power: charged_time > charge_max_time_now, enough!\n"); | ||
225 | /* have charged too long and deltaV detection did not work! */ | 325 | /* have charged too long and deltaV detection did not work! */ |
326 | powermgmt_last_cycle_level = battery_level(); | ||
327 | powermgmt_last_cycle_startstop_min = 0; | ||
226 | charger_enable(false); | 328 | charger_enable(false); |
227 | snprintf(power_message, POWER_MESSAGE_LEN, "Chg tmout %d min", CHARGE_MAX_TIME); | 329 | snprintf(power_message, POWER_MESSAGE_LEN, "Chg tmout %d min", charge_max_time_now); |
228 | /* Perhaps we should disable charging for several | 330 | /* disable charging for several hours from this point, just to be sure */ |
229 | hours from this point, just to be sure. */ | 331 | charge_pause = CHARGE_PAUSE_LEN; |
230 | } else { | 332 | } else { |
231 | if (charged_time > CHARGE_MIN_TIME) { | 333 | if (charged_time > CHARGE_MIN_TIME) { |
232 | /* have charged continuously over the minimum charging time, | 334 | /* have charged continuously over the minimum charging time, |
@@ -244,8 +346,12 @@ static void power_thread(void) | |||
244 | 346 | ||
245 | if (delta < -100) { /* delta < -10 mV */ | 347 | if (delta < -100) { /* delta < -10 mV */ |
246 | DEBUGF("power: short-term negative delta, enough!\n"); | 348 | DEBUGF("power: short-term negative delta, enough!\n"); |
349 | powermgmt_last_cycle_level = battery_level(); | ||
350 | powermgmt_last_cycle_startstop_min = 0; | ||
247 | charger_enable(false); | 351 | charger_enable(false); |
248 | snprintf(power_message, POWER_MESSAGE_LEN, "end negd %d %dmin", delta, charged_time); | 352 | snprintf(power_message, POWER_MESSAGE_LEN, "end negd %d %dmin", delta, charged_time); |
353 | /* disable charging for several hours from this point, just to be sure */ | ||
354 | charge_pause = CHARGE_PAUSE_LEN; | ||
249 | } else { | 355 | } else { |
250 | /* if we didn't disable the charger in the previous test, check for low positive delta */ | 356 | /* if we didn't disable the charger in the previous test, check for low positive delta */ |
251 | delta = ( power_history[POWER_HISTORY_LEN-1] * 100 | 357 | delta = ( power_history[POWER_HISTORY_LEN-1] * 100 |
@@ -256,8 +362,12 @@ static void power_thread(void) | |||
256 | 362 | ||
257 | if (delta < 1) { /* delta < 0.1 mV */ | 363 | if (delta < 1) { /* delta < 0.1 mV */ |
258 | DEBUGF("power: long-term small positive delta, enough!\n"); | 364 | DEBUGF("power: long-term small positive delta, enough!\n"); |
365 | powermgmt_last_cycle_level = battery_level(); | ||
366 | powermgmt_last_cycle_startstop_min = 0; | ||
259 | charger_enable(false); | 367 | charger_enable(false); |
260 | snprintf(power_message, POWER_MESSAGE_LEN, "end lowd %d %dmin", delta, charged_time); | 368 | snprintf(power_message, POWER_MESSAGE_LEN, "end lowd %d %dmin", delta, charged_time); |
369 | /* disable charging for several hours from this point, just to be sure */ | ||
370 | charge_pause = CHARGE_PAUSE_LEN; | ||
261 | } | 371 | } |
262 | } | 372 | } |
263 | } | 373 | } |
@@ -266,15 +376,33 @@ static void power_thread(void) | |||
266 | /* charged inserted but not enabled */ | 376 | /* charged inserted but not enabled */ |
267 | /* if battery is not full, enable charging */ | 377 | /* if battery is not full, enable charging */ |
268 | if (battery_level() < charge_restart_level) { | 378 | if (battery_level() < charge_restart_level) { |
379 | if (charge_pause) { | ||
380 | DEBUGF("power: batt level < restart level, but charge pause, not enabling\n"); | ||
381 | snprintf(power_message, POWER_MESSAGE_LEN, "chg pause %d min", charge_pause); | ||
382 | } else { | ||
383 | /* calculate max charge time depending on current battery level */ | ||
384 | /* take 20% more because battery level is not linear */ | ||
385 | charge_max_time_now = CHARGE_MAX_TIME * (100 + 30 - battery_level()) / 100; | ||
386 | if (charge_max_time_now > CHARGE_MAX_TIME) { | ||
387 | charge_max_time_now = CHARGE_MAX_TIME; | ||
388 | } | ||
389 | snprintf(power_message, POWER_MESSAGE_LEN, "ChgAt %d%% max %dm", battery_level(), charge_max_time_now); | ||
390 | |||
391 | /* enable the charger after the max time calc is done, because battery_level */ | ||
392 | /* depends on if the charger is on */ | ||
269 | DEBUGF("power: charger inserted and battery not full, enabling\n"); | 393 | DEBUGF("power: charger inserted and battery not full, enabling\n"); |
270 | charger_enable(true); | 394 | powermgmt_last_cycle_level = battery_level(); |
395 | powermgmt_last_cycle_startstop_min = 0; | ||
271 | charged_time = 0; | 396 | charged_time = 0; |
397 | |||
398 | charger_enable(true); | ||
399 | |||
272 | /* clear the power history so that we don't use values before | 400 | /* clear the power history so that we don't use values before |
273 | * discharge for the long-term delta | 401 | * discharge for the long-term delta |
274 | */ | 402 | */ |
275 | for (i = 0; i < POWER_HISTORY_LEN-1; i++) | 403 | for (i = 0; i < POWER_HISTORY_LEN-1; i++) |
276 | power_history[i] = power_history[POWER_HISTORY_LEN-1]; | 404 | power_history[i] = power_history[POWER_HISTORY_LEN-1]; |
277 | snprintf(power_message, POWER_MESSAGE_LEN, "Chg started at %d%%", battery_level()); | 405 | } |
278 | } | 406 | } |
279 | } | 407 | } |
280 | } else { | 408 | } else { |
@@ -282,11 +410,15 @@ static void power_thread(void) | |||
282 | if (charger_enabled) { | 410 | if (charger_enabled) { |
283 | /* charger not inserted but was enabled */ | 411 | /* charger not inserted but was enabled */ |
284 | DEBUGF("power: charger disconnected, disabling\n"); | 412 | DEBUGF("power: charger disconnected, disabling\n"); |
413 | powermgmt_last_cycle_level = battery_level(); | ||
414 | powermgmt_last_cycle_startstop_min = 0; | ||
285 | charger_enable(false); | 415 | charger_enable(false); |
286 | snprintf(power_message, POWER_MESSAGE_LEN, "Charger disc"); | 416 | snprintf(power_message, POWER_MESSAGE_LEN, "Charger disc"); |
287 | } | 417 | } |
288 | /* charger not inserted and disabled, so we're discharging */ | 418 | /* charger not inserted and disabled, so we're discharging */ |
289 | } | 419 | } |
420 | powermgmt_last_cycle_startstop_min++; | ||
421 | |||
290 | #endif /* HAVE_CHARGE_CTRL*/ | 422 | #endif /* HAVE_CHARGE_CTRL*/ |
291 | 423 | ||
292 | /* sleep for roughly a minute */ | 424 | /* sleep for roughly a minute */ |
@@ -303,6 +435,8 @@ void power_init(void) | |||
303 | /* initialize the history with a single sample to prevent level | 435 | /* initialize the history with a single sample to prevent level |
304 | flickering during the first minute of execution */ | 436 | flickering during the first minute of execution */ |
305 | power_history[POWER_HISTORY_LEN-1] = (adc_read(ADC_UNREG_POWER) * BATTERY_SCALE_FACTOR) / 10000; | 437 | power_history[POWER_HISTORY_LEN-1] = (adc_read(ADC_UNREG_POWER) * BATTERY_SCALE_FACTOR) / 10000; |
438 | /* calculate the remaining time to that the info screen displays something useful */ | ||
439 | powermgmt_est_runningtime_min = battery_level() * BATTERY_CAPACITY / 100 * 60 / CURRENT_NORMAL; | ||
306 | 440 | ||
307 | #ifdef HAVE_CHARGE_CTRL | 441 | #ifdef HAVE_CHARGE_CTRL |
308 | snprintf(power_message, POWER_MESSAGE_LEN, "Powermgmt started"); | 442 | snprintf(power_message, POWER_MESSAGE_LEN, "Powermgmt started"); |
diff --git a/firmware/powermgmt.h b/firmware/powermgmt.h index 329bf6005f..f0c34a4fb1 100644 --- a/firmware/powermgmt.h +++ b/firmware/powermgmt.h | |||
@@ -24,7 +24,7 @@ | |||
24 | #define BATTERY_LEVEL_SHUTDOWN 450 /* 4.5V */ | 24 | #define BATTERY_LEVEL_SHUTDOWN 450 /* 4.5V */ |
25 | #define BATTERY_LEVEL_EMPTY 465 /* 4.65V */ | 25 | #define BATTERY_LEVEL_EMPTY 465 /* 4.65V */ |
26 | #define BATTERY_LEVEL_DANGEROUS 475 /* 4.75V */ | 26 | #define BATTERY_LEVEL_DANGEROUS 475 /* 4.75V */ |
27 | #define BATTERY_LEVEL_FULL 520 /* 5.2V */ | 27 | #define BATTERY_LEVEL_FULL 585 /* 5.85V */ |
28 | 28 | ||
29 | #define BATTERY_RANGE (BATTERY_LEVEL_FULL - BATTERY_LEVEL_EMPTY) | 29 | #define BATTERY_RANGE (BATTERY_LEVEL_FULL - BATTERY_LEVEL_EMPTY) |
30 | 30 | ||
@@ -39,15 +39,27 @@ | |||
39 | 39 | ||
40 | #ifdef HAVE_CHARGE_CTRL | 40 | #ifdef HAVE_CHARGE_CTRL |
41 | #define POWER_MESSAGE_LEN 32 /* power thread status message */ | 41 | #define POWER_MESSAGE_LEN 32 /* power thread status message */ |
42 | #define CHARGE_MAX_TIME 6*60 /* minutes: maximum charging time */ | 42 | #define CHARGE_MAX_TIME 8*60 /* minutes: maximum charging time */ |
43 | #define CHARGE_MIN_TIME 10 /* minutes: minimum charging time */ | 43 | #define CHARGE_MIN_TIME 10 /* minutes: minimum charging time */ |
44 | #define CHARGE_RESTART_HI 95 /* %: when to restart charging in 'charge' mode */ | 44 | #define CHARGE_RESTART_HI 95 /* %: when to restart charging in 'charge' mode */ |
45 | #define CHARGE_RESTART_LO 10 /* %: when to restart charging in 'discharge' mode */ | 45 | #define CHARGE_RESTART_LO 10 /* %: when to restart charging in 'discharge' mode */ |
46 | #define CHARGE_PAUSE_LEN 60 /* how many minutes to pause between charging cycles */ | ||
46 | 47 | ||
47 | extern char power_message[POWER_MESSAGE_LEN]; | 48 | extern char power_message[POWER_MESSAGE_LEN]; |
48 | extern char charge_restart_level; | 49 | extern char charge_restart_level; |
50 | |||
51 | extern int powermgmt_last_cycle_startstop_min; /* how many minutes ago was the charging started or stopped? */ | ||
52 | extern int powermgmt_last_cycle_level; /* which level had the batteries at this time? */ | ||
53 | |||
54 | extern int battery_lazyness[20]; /* how does the battery react when plugging in/out the charger */ | ||
55 | |||
49 | #endif /* HAVE_CHARGE_CTRL */ | 56 | #endif /* HAVE_CHARGE_CTRL */ |
50 | 57 | ||
58 | #define BATTERY_CAPACITY 1800 /* battery capacity in mAh for runtime estimation */ | ||
59 | #define CURRENT_NORMAL 145 /* usual current in mA when using the AJB including some disk/backlight/... activity */ | ||
60 | #define CURRENT_BACKLIGHT 30 /* additional current when backlight is always on */ | ||
61 | #define CURRENT_CHARGING 300 /* charging current */ | ||
62 | |||
51 | extern unsigned short power_history[POWER_HISTORY_LEN]; | 63 | extern unsigned short power_history[POWER_HISTORY_LEN]; |
52 | 64 | ||
53 | /* Start up power management thread */ | 65 | /* Start up power management thread */ |
@@ -57,6 +69,7 @@ void power_init(void); | |||
57 | 69 | ||
58 | /* Returns battery level in percent */ | 70 | /* Returns battery level in percent */ |
59 | int battery_level(void); | 71 | int battery_level(void); |
72 | int battery_time(void); /* minutes */ | ||
60 | 73 | ||
61 | /* Tells if the battery level is safe for disk writes */ | 74 | /* Tells if the battery level is safe for disk writes */ |
62 | bool battery_level_safe(void); | 75 | bool battery_level_safe(void); |