1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
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 ****************************************************************************/
27 #define BATTERY_LOG "/battery_bench.txt"
28 #define BUF_SIZE 16000
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
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"
188 #elif CONFIG_KEYPAD == SAMSUNG_YH_PAD
190 #define BATTERY_ON BUTTON_LEFT
191 #define BATTERY_OFF BUTTON_RIGHT
192 #define BATTERY_ON_TXT "LEFT"
193 #define BATTERY_OFF_TXT "RIGHT"
196 #error No keymap defined!
199 #ifdef HAVE_TOUCHSCREEN
201 #define BATTERY_ON BUTTON_CENTER
204 #define BATTERY_OFF BUTTON_TOPLEFT
206 #ifndef BATTERY_ON_TXT
207 #define BATTERY_ON_TXT "CENTRE - start"
209 #ifndef BATTERY_OFF_TXT
210 #define BATTERY_OFF_TXT "TOPLEFT"
214 /****************************** Plugin Entry Point ****************************/
220 enum plugin_status
plugin_start(const void* parameter
)
227 /* Struct for battery information */
230 /* the size of the struct elements is optimised to make the struct size
234 unsigned int voltage
;
236 unsigned short flags
;
237 } bat
[BUF_SIZE
/sizeof(struct batt_info
)];
239 #define BUF_ELEMENTS (sizeof(bat)/sizeof(struct batt_info))
241 static unsigned int thread_id
;
242 static struct event_queue thread_q
;
243 static bool in_usb_mode
;
244 static unsigned int buf_idx
;
246 bool exit_tsr(bool reenter
)
250 rb
->lcd_clear_display();
251 rb
->lcd_puts_scroll(0, 0, "Batt.Bench is currently running.");
252 rb
->lcd_puts_scroll(0, 1, "Press " BATTERY_OFF_TXT
" to cancel the test");
253 #ifdef HAVE_LCD_BITMAP
254 rb
->lcd_puts_scroll(0, 2, "Anything else will resume");
260 button
= rb
->button_get(true);
261 if (IS_SYSEVENT(button
))
263 if (button
== BATTERY_OFF
)
265 rb
->queue_post(&thread_q
, EV_EXIT
, 0);
266 rb
->thread_wait(thread_id
);
267 /* remove the thread's queue from the broadcast list */
268 rb
->queue_delete(&thread_q
);
275 #define BIT_CHARGER 0x1
276 #define BIT_CHARGING 0x2
277 #define BIT_USB_POWER 0x4
279 #define HMS(x) (x)/3600,((x)%3600)/60,((x)%3600)%60
281 /* use long for aligning */
282 unsigned long thread_stack
[THREAD_STACK_SIZE
/sizeof(long)];
284 #if CONFIG_CHARGING || defined(HAVE_USB_POWER)
285 static unsigned int charge_state(void)
287 unsigned int ret
= 0;
289 if (rb
->charger_inserted())
291 #if CONFIG_CHARGING >= CHARGING_MONITOR
292 if (rb
->charging_state())
296 #ifdef HAVE_USB_POWER
297 if (rb
->usb_powered())
298 ret
|= BIT_USB_POWER
;
305 static bool flush_buffer(void)
310 /* don't access the disk when in usb mode, or when no data is available */
311 if (in_usb_mode
|| (buf_idx
== 0))
316 fd
= rb
->open(BATTERY_LOG
, O_RDWR
| O_CREAT
| O_APPEND
);
322 for (i
= 0; i
< buf_idx
; i
++)
324 secs
= bat
[i
].ticks
/HZ
;
326 "%02d:%02d:%02d, %05d, %03d%%, "
330 #if CONFIG_CHARGING >= CHARGING_MONITOR
334 #ifdef HAVE_USB_POWER
339 HMS(secs
), secs
, bat
[i
].level
,
340 bat
[i
].eta
/ 60, bat
[i
].eta
% 60,
343 , (bat
[i
].flags
& BIT_CHARGER
) ? 'A' : '-'
344 #if CONFIG_CHARGING >= CHARGING_MONITOR
345 , (bat
[i
].flags
& BIT_CHARGING
) ? 'C' : '-'
348 #ifdef HAVE_USB_POWER
349 , (bat
[i
].flags
& BIT_USB_POWER
) ? 'U' : '-'
363 char *exit_reason
= "unknown";
364 long sleep_time
= 60 * HZ
;
365 struct queue_event ev
;
373 /* add data to buffer */
374 if (buf_idx
< BUF_ELEMENTS
)
376 bat
[buf_idx
].ticks
= *rb
->current_tick
;
377 bat
[buf_idx
].level
= rb
->battery_level();
378 bat
[buf_idx
].eta
= rb
->battery_time();
379 bat
[buf_idx
].voltage
= rb
->battery_voltage();
380 #if CONFIG_CHARGING || defined(HAVE_USB_POWER)
381 bat
[buf_idx
].flags
= charge_state();
384 rb
->register_storage_idle_func(flush_buffer
);
387 /* What to do when the measurement buffer is full:
388 1) save our measurements to disk but waste some power doing so?
389 2) throw away measurements to save some power?
390 The choice made here is to save the measurements. It is quite unusual
391 for this to occur because it requires > 16 hours of no disk activity.
393 if (buf_idx
== BUF_ELEMENTS
) {
397 /* sleep some time until next measurement */
398 rb
->queue_wait_w_tmo(&thread_q
, &ev
, sleep_time
);
401 case SYS_USB_CONNECTED
:
403 rb
->usb_acknowledge(SYS_USB_CONNECTED_ACK
);
405 case SYS_USB_DISCONNECTED
:
407 rb
->usb_acknowledge(SYS_USB_DISCONNECTED_ACK
);
410 exit_reason
= "power off";
414 #ifdef HAVE_LCD_BITMAP
415 rb
->splash(HZ
, "Exiting battery_bench...");
417 rb
->splash(HZ
, "bench exit");
419 exit_reason
= "plugin exit";
425 /* unregister flush callback and flush to disk */
426 rb
->unregister_storage_idle_func(flush_buffer
, true);
428 /* log end of bench and exit reason */
429 fd
= rb
->open(BATTERY_LOG
, O_RDWR
| O_CREAT
| O_APPEND
);
432 rb
->fdprintf(fd
, "--Battery bench ended, reason: %s--\n", exit_reason
);
438 #ifdef HAVE_LCD_BITMAP
439 typedef void (*plcdfunc
)(int x
, int y
, const unsigned char *str
);
441 static void put_centered_str(const char* str
, plcdfunc putsxy
, int lcd_width
, int line
)
444 rb
->lcd_getstringsize(str
, &strwdt
, &strhgt
);
445 putsxy((lcd_width
- strwdt
)/2, line
*(strhgt
), str
);
453 #ifdef HAVE_LCD_BITMAP
455 const char *msgs
[] = { "Battery Benchmark","Check file", BATTERY_LOG
,
456 "for more info", BATTERY_ON_TXT
, BATTERY_OFF_TXT
" - quit" };
458 rb
->lcd_clear_display();
460 #ifdef HAVE_LCD_BITMAP
461 rb
->lcd_clear_display();
462 rb
->lcd_setfont(FONT_SYSFIXED
);
464 for (i
= 0; i
<(int)(sizeof(msgs
)/sizeof(char *)); i
++)
465 put_centered_str(msgs
[i
],rb
->lcd_putsxy
,LCD_WIDTH
,i
+1);
467 rb
->lcd_puts_scroll(0, 0, "Batt.Bench.");
468 rb
->lcd_puts_scroll(0, 1, "PLAY/STOP");
472 #ifdef HAVE_REMOTE_LCD
473 rb
->lcd_remote_clear_display();
474 put_centered_str(msgs
[0],rb
->lcd_remote_putsxy
,LCD_REMOTE_WIDTH
,0);
475 put_centered_str(msgs
[sizeof(msgs
)/sizeof(char*)-2],
476 rb
->lcd_remote_putsxy
,LCD_REMOTE_WIDTH
,1);
477 put_centered_str(msgs
[sizeof(msgs
)/sizeof(char*)-1],
478 rb
->lcd_remote_putsxy
,LCD_REMOTE_WIDTH
,2);
479 rb
->lcd_remote_update();
484 button
= rb
->button_get(true);
494 #ifdef BATTERY_RC_OFF
500 if (rb
->default_event_handler(button
) == SYS_USB_CONNECTED
)
501 return PLUGIN_USB_CONNECTED
;
505 fd
= rb
->open(BATTERY_LOG
, O_RDONLY
);
508 fd
= rb
->open(BATTERY_LOG
, O_RDWR
| O_CREAT
);
512 "This plugin will log your battery performance in a\n"
513 "file (%s) every minute.\n"
514 "To properly test your battery:\n"
515 "1) Select and playback an album. "
516 "(Be sure to be more than the player's buffer)\n"
517 "2) Set to repeat.\n"
518 "3) Let the player run completely out of battery.\n"
519 "4) Recharge and copy (or whatever you want) the txt file to "
521 "Now you can make graphs with the data of the battery log.\n"
522 "Do not enter another plugin during the test or else the "
523 "logging activity will end.\n\n"
524 "P.S: You can decide how you will make your tests.\n"
525 "Just don't open another plugin to be sure that your log "
526 "will continue.\n\n",BATTERY_LOG
);
528 "Battery bench run for %s version %s\n\n"
529 ,MODEL_NAME
,rb
->appsversion
);
532 "Battery type: %d mAh Buffer Entries: %d\n"
533 " Time:, Seconds:, Level:, Time Left:, Voltage[mV]:"
537 #if CONFIG_CHARGING >= CHARGING_MONITOR
540 #ifdef HAVE_USB_POWER
544 ,rb
->global_settings
->battery_capacity
,
550 rb
->splash(HZ
/ 2, "Cannot create file!");
557 fd
= rb
->open(BATTERY_LOG
, O_RDWR
| O_APPEND
);
558 rb
->fdprintf(fd
, "\n--File already present. Resuming Benchmark--\n");
560 "Battery bench run for %s version %s\n\n"
561 ,MODEL_NAME
,rb
->appsversion
);
565 rb
->queue_init(&thread_q
, true); /* put the thread's queue in the bcast list */
566 if ((thread_id
= rb
->create_thread(thread
, thread_stack
,
567 sizeof(thread_stack
), 0, "Battery Benchmark"
568 IF_PRIO(, PRIORITY_BACKGROUND
)
569 IF_COP(, CPU
))) == 0)
571 rb
->splash(HZ
, "Cannot create thread!");
575 rb
->plugin_tsr(exit_tsr
);