Fix the pitch detector plugin for iaudioM3
[kugel-rb.git] / apps / plugins / battery_bench.c
blob909de035127a6a120fd593693ae3a2e81e0aca6f
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 ****************************************************************************/
23 #include "version.h"
24 #include "plugin.h"
25 PLUGIN_HEADER
27 #define BATTERY_LOG "/battery_bench.txt"
28 #define BUF_SIZE 16000
30 #define EV_EXIT 1337
32 /* seems to work with 1300, but who knows... */
33 #define THREAD_STACK_SIZE DEFAULT_STACK_SIZE + 0x200
35 #if CONFIG_KEYPAD == RECORDER_PAD
37 #define BATTERY_ON BUTTON_PLAY
38 #define BATTERY_OFF BUTTON_OFF
39 #define BATTERY_ON_TXT "PLAY - start"
40 #define BATTERY_OFF_TXT "OFF"
42 #if BUTTON_REMOTE != 0
43 #define BATTERY_RC_ON BUTTON_RC_PLAY
44 #define BATTERY_RC_OFF BUTTON_RC_STOP
45 #endif
47 #elif CONFIG_KEYPAD == ONDIO_PAD
49 #define BATTERY_ON BUTTON_RIGHT
50 #define BATTERY_OFF BUTTON_OFF
51 #define BATTERY_ON_TXT "RIGHT - start"
52 #define BATTERY_OFF_TXT "OFF"
54 #elif CONFIG_KEYPAD == PLAYER_PAD
56 #define BATTERY_ON BUTTON_PLAY
57 #define BATTERY_OFF BUTTON_STOP
58 #define BATTERY_ON_TXT "PLAY - start"
59 #define BATTERY_OFF_TXT "STOP"
61 #define BATTERY_RC_ON BUTTON_RC_PLAY
62 #define BATTERY_RC_OFF BUTTON_RC_STOP
64 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
65 (CONFIG_KEYPAD == IRIVER_H300_PAD)
67 #define BATTERY_ON BUTTON_ON
68 #define BATTERY_RC_ON BUTTON_RC_ON
70 #define BATTERY_OFF BUTTON_OFF
71 #define BATTERY_RC_OFF BUTTON_RC_STOP
73 #define BATTERY_ON_TXT "PLAY - start"
74 #define BATTERY_OFF_TXT "STOP"
76 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
77 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
78 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
80 #define BATTERY_ON BUTTON_PLAY
81 #define BATTERY_OFF BUTTON_MENU
82 #define BATTERY_ON_TXT "PLAY - start"
83 #define BATTERY_OFF_TXT "MENU"
85 #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
87 #define BATTERY_ON BUTTON_SELECT
88 #define BATTERY_OFF BUTTON_POWER
89 #define BATTERY_ON_TXT "SELECT - start"
90 #define BATTERY_OFF_TXT "POWER"
92 #elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD
94 #define BATTERY_ON BUTTON_SELECT
95 #define BATTERY_OFF BUTTON_PLAY
96 #define BATTERY_ON_TXT "SELECT - start"
97 #define BATTERY_OFF_TXT "PLAY"
99 #elif (CONFIG_KEYPAD == SANSA_E200_PAD) || \
100 (CONFIG_KEYPAD == SANSA_C200_PAD) || \
101 (CONFIG_KEYPAD == SANSA_CLIP_PAD) || \
102 (CONFIG_KEYPAD == SANSA_M200_PAD)
103 #define BATTERY_ON BUTTON_SELECT
104 #define BATTERY_OFF BUTTON_POWER
105 #define BATTERY_ON_TXT "SELECT - start"
106 #define BATTERY_OFF_TXT "POWER"
108 #elif (CONFIG_KEYPAD == SANSA_FUZE_PAD)
109 #define BATTERY_ON BUTTON_SELECT
110 #define BATTERY_OFF BUTTON_HOME
111 #define BATTERY_ON_TXT "SELECT - start"
112 #define BATTERY_OFF_TXT "HOME"
114 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
116 #define BATTERY_ON BUTTON_PLAY
117 #define BATTERY_OFF BUTTON_POWER
118 #define BATTERY_ON_TXT "PLAY - start"
119 #define BATTERY_OFF_TXT "POWER"
121 #elif CONFIG_KEYPAD == GIGABEAT_PAD
123 #define BATTERY_ON BUTTON_SELECT
124 #define BATTERY_OFF BUTTON_POWER
125 #define BATTERY_ON_TXT "SELECT - start"
126 #define BATTERY_OFF_TXT "POWER"
128 #elif CONFIG_KEYPAD == GIGABEAT_S_PAD
130 #define BATTERY_ON BUTTON_SELECT
131 #define BATTERY_OFF BUTTON_BACK
132 #define BATTERY_ON_TXT "SELECT - start"
133 #define BATTERY_OFF_TXT "BACK"
135 #elif CONFIG_KEYPAD == MROBE500_PAD
137 #define BATTERY_ON BUTTON_RC_PLAY
138 #define BATTERY_OFF BUTTON_POWER
139 #define BATTERY_ON_TXT "PLAY - start"
140 #define BATTERY_OFF_TXT "POWER"
142 #elif CONFIG_KEYPAD == MROBE100_PAD
144 #define BATTERY_ON BUTTON_SELECT
145 #define BATTERY_OFF BUTTON_POWER
146 #define BATTERY_ON_TXT "SELECT - start"
147 #define BATTERY_OFF_TXT "POWER"
149 #elif CONFIG_KEYPAD == IAUDIO_M3_PAD
151 #define BATTERY_ON BUTTON_PLAY
152 #define BATTERY_OFF BUTTON_REC
153 #define BATTERY_RC_ON BUTTON_RC_PLAY
154 #define BATTERY_RC_OFF BUTTON_RC_REC
155 #define BATTERY_ON_TXT "PLAY - start"
156 #define BATTERY_OFF_TXT "REC"
158 #elif CONFIG_KEYPAD == COWOND2_PAD
160 #define BATTERY_OFF BUTTON_POWER
161 #define BATTERY_OFF_TXT "POWER"
163 #elif CONFIG_KEYPAD == IAUDIO67_PAD
165 #define BATTERY_OFF BUTTON_POWER
166 #define BATTERY_OFF_TXT "POWER"
167 #define BATTERY_ON BUTTON_PLAY
168 #define BATTERY_ON_TXT "PLAY - start"
170 #elif CONFIG_KEYPAD == CREATIVEZVM_PAD
171 #define BATTERY_ON BUTTON_PLAY
172 #define BATTERY_ON_TXT "PLAY - start"
173 #define BATTERY_OFF BUTTON_BACK
174 #define BATTERY_OFF_TXT "BACK"
176 #elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD
178 #define BATTERY_ON BUTTON_MENU
179 #define BATTERY_OFF BUTTON_POWER
180 #define BATTERY_ON_TXT "MENU - start"
181 #define BATTERY_OFF_TXT "POWER"
183 #elif CONFIG_KEYPAD == ONDAVX747_PAD
185 #define BATTERY_OFF BUTTON_POWER
186 #define BATTERY_OFF_TXT "POWER"
187 #elif CONFIG_KEYPAD == ONDAVX777_PAD
189 #define BATTERY_OFF BUTTON_POWER
190 #define BATTERY_OFF_TXT "POWER"
192 #elif CONFIG_KEYPAD == SAMSUNG_YH_PAD
194 #define BATTERY_ON BUTTON_LEFT
195 #define BATTERY_OFF BUTTON_RIGHT
196 #define BATTERY_ON_TXT "LEFT"
197 #define BATTERY_OFF_TXT "RIGHT"
199 #else
200 #error No keymap defined!
201 #endif
203 #ifdef HAVE_TOUCHSCREEN
204 #ifndef BATTERY_ON
205 #define BATTERY_ON BUTTON_CENTER
206 #endif
207 #ifndef BATTERY_OFF
208 #define BATTERY_OFF BUTTON_TOPLEFT
209 #endif
210 #ifndef BATTERY_ON_TXT
211 #define BATTERY_ON_TXT "CENTRE - start"
212 #endif
213 #ifndef BATTERY_OFF_TXT
214 #define BATTERY_OFF_TXT "TOPLEFT"
215 #endif
216 #endif
218 /****************************** Plugin Entry Point ****************************/
219 int main(void);
220 bool exit_tsr(bool);
221 void thread(void);
224 enum plugin_status plugin_start(const void* parameter)
226 (void)parameter;
228 return main();
231 /* Struct for battery information */
232 struct batt_info
234 /* the size of the struct elements is optimised to make the struct size
235 * a power of 2 */
236 long ticks;
237 int eta;
238 unsigned int voltage;
239 short level;
240 unsigned short flags;
241 } bat[BUF_SIZE/sizeof(struct batt_info)];
243 #define BUF_ELEMENTS (sizeof(bat)/sizeof(struct batt_info))
245 static unsigned int thread_id;
246 static struct event_queue thread_q;
247 static bool in_usb_mode;
248 static unsigned int buf_idx;
250 bool exit_tsr(bool reenter)
252 long button;
253 (void)reenter;
254 rb->lcd_clear_display();
255 rb->lcd_puts_scroll(0, 0, "Batt.Bench is currently running.");
256 rb->lcd_puts_scroll(0, 1, "Press " BATTERY_OFF_TXT " to cancel the test");
257 #ifdef HAVE_LCD_BITMAP
258 rb->lcd_puts_scroll(0, 2, "Anything else will resume");
259 #endif
260 rb->lcd_update();
262 while (1)
264 button = rb->button_get(true);
265 if (IS_SYSEVENT(button))
266 continue;
267 if (button == BATTERY_OFF)
269 rb->queue_post(&thread_q, EV_EXIT, 0);
270 rb->thread_wait(thread_id);
271 /* remove the thread's queue from the broadcast list */
272 rb->queue_delete(&thread_q);
273 return true;
275 else return false;
279 #define BIT_CHARGER 0x1
280 #define BIT_CHARGING 0x2
281 #define BIT_USB_POWER 0x4
283 #define HMS(x) (x)/3600,((x)%3600)/60,((x)%3600)%60
285 /* use long for aligning */
286 unsigned long thread_stack[THREAD_STACK_SIZE/sizeof(long)];
288 #if CONFIG_CHARGING || defined(HAVE_USB_POWER)
289 static unsigned int charge_state(void)
291 unsigned int ret = 0;
292 #if CONFIG_CHARGING
293 if (rb->charger_inserted())
294 ret = BIT_CHARGER;
295 #if CONFIG_CHARGING >= CHARGING_MONITOR
296 if (rb->charging_state())
297 ret |= BIT_CHARGING;
298 #endif
299 #endif
300 #ifdef HAVE_USB_POWER
301 if (rb->usb_powered())
302 ret |= BIT_USB_POWER;
303 #endif
304 return ret;
306 #endif
309 static bool flush_buffer(void)
311 int fd, secs;
312 unsigned int i;
314 /* don't access the disk when in usb mode, or when no data is available */
315 if (in_usb_mode || (buf_idx == 0))
317 return false;
320 fd = rb->open(BATTERY_LOG, O_RDWR | O_CREAT | O_APPEND);
321 if (fd < 0)
323 return false;
326 for (i = 0; i < buf_idx; i++)
328 secs = bat[i].ticks/HZ;
329 rb->fdprintf(fd,
330 "%02d:%02d:%02d, %05d, %03d%%, "
331 "%02d:%02d, %04d, "
332 #if CONFIG_CHARGING
333 " %c"
334 #if CONFIG_CHARGING >= CHARGING_MONITOR
335 ", %c"
336 #endif
337 #endif
338 #ifdef HAVE_USB_POWER
339 ", %c"
340 #endif
341 "\n",
343 HMS(secs), secs, bat[i].level,
344 bat[i].eta / 60, bat[i].eta % 60,
345 bat[i].voltage
346 #if CONFIG_CHARGING
347 , (bat[i].flags & BIT_CHARGER) ? 'A' : '-'
348 #if CONFIG_CHARGING >= CHARGING_MONITOR
349 , (bat[i].flags & BIT_CHARGING) ? 'C' : '-'
350 #endif
351 #endif
352 #ifdef HAVE_USB_POWER
353 , (bat[i].flags & BIT_USB_POWER) ? 'U' : '-'
354 #endif
357 rb->close(fd);
359 buf_idx = 0;
360 return true;
364 void thread(void)
366 bool exit = false;
367 char *exit_reason = "unknown";
368 long sleep_time = 60 * HZ;
369 struct queue_event ev;
370 int fd;
372 in_usb_mode = false;
373 buf_idx = 0;
375 while (!exit)
377 /* add data to buffer */
378 if (buf_idx < BUF_ELEMENTS)
380 bat[buf_idx].ticks = *rb->current_tick;
381 bat[buf_idx].level = rb->battery_level();
382 bat[buf_idx].eta = rb->battery_time();
383 bat[buf_idx].voltage = rb->battery_voltage();
384 #if CONFIG_CHARGING || defined(HAVE_USB_POWER)
385 bat[buf_idx].flags = charge_state();
386 #endif
387 buf_idx++;
388 rb->register_storage_idle_func(flush_buffer);
391 /* What to do when the measurement buffer is full:
392 1) save our measurements to disk but waste some power doing so?
393 2) throw away measurements to save some power?
394 The choice made here is to save the measurements. It is quite unusual
395 for this to occur because it requires > 16 hours of no disk activity.
397 if (buf_idx == BUF_ELEMENTS) {
398 flush_buffer();
401 /* sleep some time until next measurement */
402 rb->queue_wait_w_tmo(&thread_q, &ev, sleep_time);
403 switch (ev.id)
405 case SYS_USB_CONNECTED:
406 in_usb_mode = true;
407 rb->usb_acknowledge(SYS_USB_CONNECTED_ACK);
408 break;
409 case SYS_USB_DISCONNECTED:
410 in_usb_mode = false;
411 rb->usb_acknowledge(SYS_USB_DISCONNECTED_ACK);
412 break;
413 case SYS_POWEROFF:
414 exit_reason = "power off";
415 exit = true;
416 break;
417 case EV_EXIT:
418 #ifdef HAVE_LCD_BITMAP
419 rb->splash(HZ, "Exiting battery_bench...");
420 #else
421 rb->splash(HZ, "bench exit");
422 #endif
423 exit_reason = "plugin exit";
424 exit = true;
425 break;
429 /* unregister flush callback and flush to disk */
430 rb->unregister_storage_idle_func(flush_buffer, true);
432 /* log end of bench and exit reason */
433 fd = rb->open(BATTERY_LOG, O_RDWR | O_CREAT | O_APPEND);
434 if (fd >= 0)
436 rb->fdprintf(fd, "--Battery bench ended, reason: %s--\n", exit_reason);
437 rb->close(fd);
442 #ifdef HAVE_LCD_BITMAP
443 typedef void (*plcdfunc)(int x, int y, const unsigned char *str);
445 static void put_centered_str(const char* str, plcdfunc putsxy, int lcd_width, int line)
447 int strwdt, strhgt;
448 rb->lcd_getstringsize(str, &strwdt, &strhgt);
449 putsxy((lcd_width - strwdt)/2, line*(strhgt), str);
451 #endif
453 int main(void)
455 int button, fd;
456 bool on = false;
457 #ifdef HAVE_LCD_BITMAP
458 int i;
459 const char *msgs[] = { "Battery Benchmark","Check file", BATTERY_LOG,
460 "for more info", BATTERY_ON_TXT, BATTERY_OFF_TXT " - quit" };
461 #endif
462 rb->lcd_clear_display();
464 #ifdef HAVE_LCD_BITMAP
465 rb->lcd_clear_display();
466 rb->lcd_setfont(FONT_SYSFIXED);
468 for (i = 0; i<(int)(sizeof(msgs)/sizeof(char *)); i++)
469 put_centered_str(msgs[i],rb->lcd_putsxy,LCD_WIDTH,i+1);
470 #else
471 rb->lcd_puts_scroll(0, 0, "Batt.Bench.");
472 rb->lcd_puts_scroll(0, 1, "PLAY/STOP");
473 #endif
474 rb->lcd_update();
476 #ifdef HAVE_REMOTE_LCD
477 rb->lcd_remote_clear_display();
478 put_centered_str(msgs[0],rb->lcd_remote_putsxy,LCD_REMOTE_WIDTH,0);
479 put_centered_str(msgs[sizeof(msgs)/sizeof(char*)-2],
480 rb->lcd_remote_putsxy,LCD_REMOTE_WIDTH,1);
481 put_centered_str(msgs[sizeof(msgs)/sizeof(char*)-1],
482 rb->lcd_remote_putsxy,LCD_REMOTE_WIDTH,2);
483 rb->lcd_remote_update();
484 #endif
488 button = rb->button_get(true);
489 switch (button)
491 case BATTERY_ON:
492 #ifdef BATTERY_RC_ON
493 case BATTERY_RC_ON:
494 #endif
495 on = true;
496 break;
497 case BATTERY_OFF:
498 #ifdef BATTERY_RC_OFF
499 case BATTERY_RC_OFF:
500 #endif
501 return PLUGIN_OK;
503 default:
504 if (rb->default_event_handler(button) == SYS_USB_CONNECTED)
505 return PLUGIN_USB_CONNECTED;
507 }while(!on);
509 fd = rb->open(BATTERY_LOG, O_RDONLY);
510 if (fd < 0)
512 fd = rb->open(BATTERY_LOG, O_RDWR | O_CREAT);
513 if (fd >= 0)
515 rb->fdprintf(fd,
516 "This plugin will log your battery performance in a\n"
517 "file (%s) every minute.\n"
518 "To properly test your battery:\n"
519 "1) Select and playback an album. "
520 "(Be sure to be more than the player's buffer)\n"
521 "2) Set to repeat.\n"
522 "3) Let the player run completely out of battery.\n"
523 "4) Recharge and copy (or whatever you want) the txt file to "
524 "your computer.\n"
525 "Now you can make graphs with the data of the battery log.\n"
526 "Do not enter another plugin during the test or else the "
527 "logging activity will end.\n\n"
528 "P.S: You can decide how you will make your tests.\n"
529 "Just don't open another plugin to be sure that your log "
530 "will continue.\n\n",BATTERY_LOG);
531 rb->fdprintf(fd,
532 "Battery bench run for %s version %s\n\n"
533 ,MODEL_NAME,rb->appsversion);
535 rb->fdprintf(fd,
536 "Battery type: %d mAh Buffer Entries: %d\n"
537 " Time:, Seconds:, Level:, Time Left:, Voltage[mV]:"
538 #if CONFIG_CHARGING
539 ", C:"
540 #endif
541 #if CONFIG_CHARGING >= CHARGING_MONITOR
542 ", S:"
543 #endif
544 #ifdef HAVE_USB_POWER
545 ", U:"
546 #endif
547 "\n"
548 ,rb->global_settings->battery_capacity,
549 (int)BUF_ELEMENTS);
550 rb->close(fd);
552 else
554 rb->splash(HZ / 2, "Cannot create file!");
555 return PLUGIN_ERROR;
558 else
560 rb->close(fd);
561 fd = rb->open(BATTERY_LOG, O_RDWR | O_APPEND);
562 rb->fdprintf(fd, "\n--File already present. Resuming Benchmark--\n");
563 rb->fdprintf(fd,
564 "Battery bench run for %s version %s\n\n"
565 ,MODEL_NAME,rb->appsversion);
566 rb->close(fd);
569 rb->queue_init(&thread_q, true); /* put the thread's queue in the bcast list */
570 if ((thread_id = rb->create_thread(thread, thread_stack,
571 sizeof(thread_stack), 0, "Battery Benchmark"
572 IF_PRIO(, PRIORITY_BACKGROUND)
573 IF_COP(, CPU))) == 0)
575 rb->splash(HZ, "Cannot create thread!");
576 return PLUGIN_ERROR;
579 rb->plugin_tsr(exit_tsr);
581 return PLUGIN_OK;