Reverting parts of r19760 that was mistakenly committed.
[kugel-rb.git] / apps / plugins / battery_bench.c
blob7c18dc74dd36a9b10b0e326011fab853940bbdb8
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
11 * Copyright (C) 2006 Alexander Spyridakis, Hristo Kovachev
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 ****************************************************************************/
22 #ifndef SIMULATOR /* not for the simulator */
24 #include "version.h"
25 #include "plugin.h"
26 PLUGIN_HEADER
28 #define BATTERY_LOG "/battery_bench.txt"
29 #define BUF_SIZE 16000
31 #define EV_EXIT 1337
33 /* seems to work with 1300, but who knows... */
34 #define THREAD_STACK_SIZE DEFAULT_STACK_SIZE + 0x200
36 #if CONFIG_KEYPAD == RECORDER_PAD
38 #define BATTERY_ON BUTTON_PLAY
39 #define BATTERY_OFF BUTTON_OFF
40 #define BATTERY_ON_TXT "PLAY - start"
41 #define BATTERY_OFF_TXT "OFF"
43 #if BUTTON_REMOTE != 0
44 #define BATTERY_RC_ON BUTTON_RC_PLAY
45 #define BATTERY_RC_OFF BUTTON_RC_STOP
46 #endif
48 #elif CONFIG_KEYPAD == ONDIO_PAD
50 #define BATTERY_ON BUTTON_RIGHT
51 #define BATTERY_OFF BUTTON_OFF
52 #define BATTERY_ON_TXT "RIGHT - start"
53 #define BATTERY_OFF_TXT "OFF"
55 #elif CONFIG_KEYPAD == PLAYER_PAD
57 #define BATTERY_ON BUTTON_PLAY
58 #define BATTERY_OFF BUTTON_STOP
59 #define BATTERY_ON_TXT "PLAY - start"
60 #define BATTERY_OFF_TXT "STOP"
62 #define BATTERY_RC_ON BUTTON_RC_PLAY
63 #define BATTERY_RC_OFF BUTTON_RC_STOP
65 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
66 (CONFIG_KEYPAD == IRIVER_H300_PAD)
68 #define BATTERY_ON BUTTON_ON
69 #define BATTERY_RC_ON BUTTON_RC_ON
71 #define BATTERY_OFF BUTTON_OFF
72 #define BATTERY_RC_OFF BUTTON_RC_STOP
74 #define BATTERY_ON_TXT "PLAY - start"
75 #define BATTERY_OFF_TXT "STOP"
77 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
78 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
79 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
81 #define BATTERY_ON BUTTON_PLAY
82 #define BATTERY_OFF BUTTON_MENU
83 #define BATTERY_ON_TXT "PLAY - start"
84 #define BATTERY_OFF_TXT "MENU"
86 #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
88 #define BATTERY_ON BUTTON_SELECT
89 #define BATTERY_OFF BUTTON_POWER
90 #define BATTERY_ON_TXT "SELECT - start"
91 #define BATTERY_OFF_TXT "POWER"
93 #elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD
95 #define BATTERY_ON BUTTON_SELECT
96 #define BATTERY_OFF BUTTON_PLAY
97 #define BATTERY_ON_TXT "SELECT - start"
98 #define BATTERY_OFF_TXT "PLAY"
100 #elif (CONFIG_KEYPAD == SANSA_E200_PAD) || \
101 (CONFIG_KEYPAD == SANSA_C200_PAD) || \
102 (CONFIG_KEYPAD == SANSA_CLIP_PAD) || \
103 (CONFIG_KEYPAD == SANSA_M200_PAD) || \
104 (CONFIG_KEYPAD == SANSA_FUZE_PAD)
105 #define BATTERY_ON BUTTON_SELECT
106 #define BATTERY_OFF BUTTON_POWER
107 #define BATTERY_ON_TXT "SELECT - start"
108 #define BATTERY_OFF_TXT "POWER"
110 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
112 #define BATTERY_ON BUTTON_PLAY
113 #define BATTERY_OFF BUTTON_POWER
114 #define BATTERY_ON_TXT "PLAY - start"
115 #define BATTERY_OFF_TXT "POWER"
117 #elif CONFIG_KEYPAD == GIGABEAT_PAD
119 #define BATTERY_ON BUTTON_SELECT
120 #define BATTERY_OFF BUTTON_POWER
121 #define BATTERY_ON_TXT "SELECT - start"
122 #define BATTERY_OFF_TXT "POWER"
124 #elif CONFIG_KEYPAD == GIGABEAT_S_PAD
126 #define BATTERY_ON BUTTON_SELECT
127 #define BATTERY_OFF BUTTON_BACK
128 #define BATTERY_ON_TXT "SELECT - start"
129 #define BATTERY_OFF_TXT "BACK"
131 #elif CONFIG_KEYPAD == MROBE500_PAD
133 #define BATTERY_ON BUTTON_RC_PLAY
134 #define BATTERY_OFF BUTTON_POWER
135 #define BATTERY_ON_TXT "PLAY - start"
136 #define BATTERY_OFF_TXT "POWER"
138 #elif CONFIG_KEYPAD == MROBE100_PAD
140 #define BATTERY_ON BUTTON_SELECT
141 #define BATTERY_OFF BUTTON_POWER
142 #define BATTERY_ON_TXT "SELECT - start"
143 #define BATTERY_OFF_TXT "POWER"
145 #elif CONFIG_KEYPAD == IAUDIO_M3_PAD
147 #define BATTERY_ON BUTTON_PLAY
148 #define BATTERY_OFF BUTTON_REC
149 #define BATTERY_RC_ON BUTTON_RC_PLAY
150 #define BATTERY_RC_OFF BUTTON_RC_REC
151 #define BATTERY_ON_TXT "PLAY - start"
152 #define BATTERY_OFF_TXT "REC"
154 #elif CONFIG_KEYPAD == COWOND2_PAD
156 #define BATTERY_OFF BUTTON_POWER
157 #define BATTERY_OFF_TXT "POWER"
159 #elif CONFIG_KEYPAD == IAUDIO67_PAD
161 #define BATTERY_OFF BUTTON_POWER
162 #define BATTERY_OFF_TXT "POWER"
163 #define BATTERY_ON BUTTON_PLAY
164 #define BATTERY_ON_TXT "PLAY - start"
166 #elif CONFIG_KEYPAD == CREATIVEZVM_PAD
167 #define BATTERY_ON BUTTON_PLAY
168 #define BATTERY_ON_TXT "PLAY - start"
169 #define BATTERY_OFF BUTTON_BACK
170 #define BATTERY_OFF_TXT "BACK"
172 #else
173 #error No keymap defined!
174 #endif
176 #ifdef HAVE_TOUCHSCREEN
177 #ifndef BATTERY_ON
178 #define BATTERY_ON BUTTON_CENTER
179 #endif
180 #ifndef BATTERY_OFF
181 #define BATTERY_OFF BUTTON_TOPLEFT
182 #endif
183 #ifndef BATTERY_ON_TXT
184 #define BATTERY_ON_TXT "CENTRE - start"
185 #endif
186 #ifndef BATTERY_OFF_TXT
187 #define BATTERY_OFF_TXT "TOPLEFT"
188 #endif
189 #endif
191 /****************************** Plugin Entry Point ****************************/
192 static const struct plugin_api* rb;
193 MEM_FUNCTION_WRAPPERS(rb);
194 int main(void);
195 bool exit_tsr(bool);
196 void thread(void);
199 enum plugin_status plugin_start(const struct plugin_api* api, const void* parameter)
201 (void)parameter;
202 rb = api;
204 return main();
207 /* Struct for battery information */
208 struct batt_info
210 /* the size of the struct elements is optimised to make the struct size
211 * a power of 2 */
212 long ticks;
213 int eta;
214 unsigned int voltage;
215 short level;
216 unsigned short flags;
217 } bat[BUF_SIZE/sizeof(struct batt_info)];
219 #define BUF_ELEMENTS (sizeof(bat)/sizeof(struct batt_info))
221 static unsigned int thread_id;
222 static struct event_queue thread_q;
223 static bool in_usb_mode;
224 static unsigned int buf_idx;
226 bool exit_tsr(bool reenter)
228 long button;
229 (void)reenter;
230 rb->lcd_clear_display();
231 rb->lcd_puts_scroll(0, 0, "Batt.Bench is currently running.");
232 rb->lcd_puts_scroll(0, 1, "Press " BATTERY_OFF_TXT " to cancel the test");
233 #ifdef HAVE_LCD_BITMAP
234 rb->lcd_puts_scroll(0, 2, "Anything else will resume");
235 #endif
236 rb->lcd_update();
238 while (1)
240 button = rb->button_get(true);
241 if (IS_SYSEVENT(button))
242 continue;
243 if (button == BATTERY_OFF)
245 rb->queue_post(&thread_q, EV_EXIT, 0);
246 rb->thread_wait(thread_id);
247 /* remove the thread's queue from the broadcast list */
248 rb->queue_delete(&thread_q);
249 return true;
251 else return false;
255 #define BIT_CHARGER 0x1
256 #define BIT_CHARGING 0x2
257 #define BIT_USB_POWER 0x4
259 #define HMS(x) (x)/3600,((x)%3600)/60,((x)%3600)%60
261 /* use long for aligning */
262 unsigned long thread_stack[THREAD_STACK_SIZE/sizeof(long)];
264 #if CONFIG_CHARGING || defined(HAVE_USB_POWER)
265 static unsigned int charge_state(void)
267 unsigned int ret = 0;
268 #if CONFIG_CHARGING
269 if (rb->charger_inserted())
270 ret = BIT_CHARGER;
271 #if CONFIG_CHARGING == CHARGING_MONITOR
272 if (rb->charging_state())
273 ret |= BIT_CHARGING;
274 #endif
275 #endif
276 #ifdef HAVE_USB_POWER
277 if (rb->usb_powered())
278 ret |= BIT_USB_POWER;
279 #endif
280 return ret;
282 #endif
285 static bool flush_buffer(void)
287 int fd, secs;
288 unsigned int i;
290 /* don't access the disk when in usb mode, or when no data is available */
291 if (in_usb_mode || (buf_idx == 0))
293 return false;
296 fd = rb->open(BATTERY_LOG, O_RDWR | O_CREAT | O_APPEND);
297 if (fd < 0)
299 return false;
302 for (i = 0; i < buf_idx; i++)
304 secs = bat[i].ticks/HZ;
305 rb->fdprintf(fd,
306 "%02d:%02d:%02d, %05d, %03d%%, "
307 "%02d:%02d, %04d, "
308 #if CONFIG_CHARGING
309 " %c"
310 #if CONFIG_CHARGING == CHARGING_MONITOR
311 ", %c"
312 #endif
313 #endif
314 #ifdef HAVE_USB_POWER
315 ", %c"
316 #endif
317 "\n",
319 HMS(secs), secs, bat[i].level,
320 bat[i].eta / 60, bat[i].eta % 60,
321 bat[i].voltage
322 #if CONFIG_CHARGING
323 , (bat[i].flags & BIT_CHARGER) ? 'A' : '-'
324 #if CONFIG_CHARGING == CHARGING_MONITOR
325 , (bat[i].flags & BIT_CHARGING) ? 'C' : '-'
326 #endif
327 #endif
328 #ifdef HAVE_USB_POWER
329 , (bat[i].flags & BIT_USB_POWER) ? 'U' : '-'
330 #endif
333 rb->close(fd);
335 buf_idx = 0;
336 return true;
340 void thread(void)
342 bool exit = false;
343 char *exit_reason = "unknown";
344 long sleep_time = 60 * HZ;
345 struct queue_event ev;
346 int fd;
348 in_usb_mode = false;
349 buf_idx = 0;
351 while (!exit)
353 /* add data to buffer */
354 if (buf_idx < BUF_ELEMENTS)
356 bat[buf_idx].ticks = *rb->current_tick;
357 bat[buf_idx].level = rb->battery_level();
358 bat[buf_idx].eta = rb->battery_time();
359 bat[buf_idx].voltage = rb->battery_voltage();
360 #if CONFIG_CHARGING || defined(HAVE_USB_POWER)
361 bat[buf_idx].flags = charge_state();
362 #endif
363 buf_idx++;
364 rb->register_storage_idle_func(flush_buffer);
367 /* What to do when the measurement buffer is full:
368 1) save our measurements to disk but waste some power doing so?
369 2) throw away measurements to save some power?
370 The choice made here is to save the measurements. It is quite unusual
371 for this to occur because it requires > 16 hours of no disk activity.
373 if (buf_idx == BUF_ELEMENTS) {
374 flush_buffer();
377 /* sleep some time until next measurement */
378 rb->queue_wait_w_tmo(&thread_q, &ev, sleep_time);
379 switch (ev.id)
381 case SYS_USB_CONNECTED:
382 in_usb_mode = true;
383 rb->usb_acknowledge(SYS_USB_CONNECTED_ACK);
384 break;
385 case SYS_USB_DISCONNECTED:
386 in_usb_mode = false;
387 rb->usb_acknowledge(SYS_USB_DISCONNECTED_ACK);
388 break;
389 case SYS_POWEROFF:
390 exit_reason = "power off";
391 exit = true;
392 break;
393 case EV_EXIT:
394 #ifdef HAVE_LCD_BITMAP
395 rb->splash(HZ, "Exiting battery_bench...");
396 #else
397 rb->splash(HZ, "bench exit");
398 #endif
399 exit_reason = "plugin exit";
400 exit = true;
401 break;
405 /* unregister flush callback and flush to disk */
406 rb->unregister_storage_idle_func(flush_buffer, true);
408 /* log end of bench and exit reason */
409 fd = rb->open(BATTERY_LOG, O_RDWR | O_CREAT | O_APPEND);
410 if (fd >= 0)
412 rb->fdprintf(fd, "--Battery bench ended, reason: %s--\n", exit_reason);
413 rb->close(fd);
418 #ifdef HAVE_LCD_BITMAP
419 typedef void (*plcdfunc)(int x, int y, const unsigned char *str);
421 static void put_centered_str(const char* str, plcdfunc putsxy, int lcd_width, int line)
423 int strwdt, strhgt;
424 rb->lcd_getstringsize(str, &strwdt, &strhgt);
425 putsxy((lcd_width - strwdt)/2, line*(strhgt), str);
427 #endif
429 int main(void)
431 int button, fd;
432 bool on = false;
433 #ifdef HAVE_LCD_BITMAP
434 int i;
435 const char *msgs[] = { "Battery Benchmark","Check file", BATTERY_LOG,
436 "for more info", BATTERY_ON_TXT, BATTERY_OFF_TXT " - quit" };
437 #endif
438 rb->lcd_clear_display();
440 #ifdef HAVE_LCD_BITMAP
441 rb->lcd_clear_display();
442 rb->lcd_setfont(FONT_SYSFIXED);
444 for (i = 0; i<(int)(sizeof(msgs)/sizeof(char *)); i++)
445 put_centered_str(msgs[i],rb->lcd_putsxy,LCD_WIDTH,i+1);
446 #else
447 rb->lcd_puts_scroll(0, 0, "Batt.Bench.");
448 rb->lcd_puts_scroll(0, 1, "PLAY/STOP");
449 #endif
450 rb->lcd_update();
452 #ifdef HAVE_REMOTE_LCD
453 rb->lcd_remote_clear_display();
454 put_centered_str(msgs[0],rb->lcd_remote_putsxy,LCD_REMOTE_WIDTH,0);
455 put_centered_str(msgs[sizeof(msgs)/sizeof(char*)-2],
456 rb->lcd_remote_putsxy,LCD_REMOTE_WIDTH,1);
457 put_centered_str(msgs[sizeof(msgs)/sizeof(char*)-1],
458 rb->lcd_remote_putsxy,LCD_REMOTE_WIDTH,2);
459 rb->lcd_remote_update();
460 #endif
464 button = rb->button_get(true);
465 switch (button)
467 case BATTERY_ON:
468 #ifdef BATTERY_RC_ON
469 case BATTERY_RC_ON:
470 #endif
471 on = true;
472 break;
473 case BATTERY_OFF:
474 #ifdef BATTERY_RC_OFF
475 case BATTERY_RC_OFF:
476 #endif
477 return PLUGIN_OK;
479 default:
480 if (rb->default_event_handler(button) == SYS_USB_CONNECTED)
481 return PLUGIN_USB_CONNECTED;
483 }while(!on);
485 fd = rb->open(BATTERY_LOG, O_RDONLY);
486 if (fd < 0)
488 fd = rb->open(BATTERY_LOG, O_RDWR | O_CREAT);
489 if (fd >= 0)
491 rb->fdprintf(fd,
492 "This plugin will log your battery performance in a\n"
493 "file (%s) every minute.\n"
494 "To properly test your battery:\n"
495 "1) Select and playback an album. "
496 "(Be sure to be more than the player's buffer)\n"
497 "2) Set to repeat.\n"
498 "3) Let the player run completely out of battery.\n"
499 "4) Recharge and copy (or whatever you want) the txt file to "
500 "your computer.\n"
501 "Now you can make graphs with the data of the battery log.\n"
502 "Do not enter another plugin during the test or else the "
503 "logging activity will end.\n\n"
504 "P.S: You can decide how you will make your tests.\n"
505 "Just don't open another plugin to be sure that your log "
506 "will continue.\n\n",BATTERY_LOG);
507 rb->fdprintf(fd,
508 "Battery bench run for %s version %s\n\n"
509 ,MODEL_NAME,rb->appsversion);
511 rb->fdprintf(fd,
512 "Battery type: %d mAh Buffer Entries: %d\n"
513 " Time:, Seconds:, Level:, Time Left:, Voltage[mV]:"
514 #if CONFIG_CHARGING
515 ", C:"
516 #endif
517 #if CONFIG_CHARGING == CHARGING_MONITOR
518 ", S:"
519 #endif
520 #ifdef HAVE_USB_POWER
521 ", U:"
522 #endif
523 "\n"
524 ,rb->global_settings->battery_capacity,
525 (int)BUF_ELEMENTS);
526 rb->close(fd);
528 else
530 rb->splash(HZ / 2, "Cannot create file!");
531 return PLUGIN_ERROR;
534 else
536 rb->close(fd);
537 fd = rb->open(BATTERY_LOG, O_RDWR | O_APPEND);
538 rb->fdprintf(fd, "\n--File already present. Resuming Benchmark--\n");
539 rb->fdprintf(fd,
540 "Battery bench run for %s version %s\n\n"
541 ,MODEL_NAME,rb->appsversion);
542 rb->close(fd);
545 rb->queue_init(&thread_q, true); /* put the thread's queue in the bcast list */
546 if ((thread_id = rb->create_thread(thread, thread_stack,
547 sizeof(thread_stack), 0, "Battery Benchmark"
548 IF_PRIO(, PRIORITY_BACKGROUND)
549 IF_COP(, CPU))) == 0)
551 rb->splash(HZ, "Cannot create thread!");
552 return PLUGIN_ERROR;
555 rb->plugin_tsr(exit_tsr);
557 return PLUGIN_OK;
560 #endif /* SIMULATOR */