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 ****************************************************************************/
22 #ifndef SIMULATOR /* not for the simulator */
28 #define BATTERY_LOG "/battery_bench.txt"
29 #define BUF_SIZE 16000
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
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 #define BATTERY_ON BUTTON_SELECT
103 #define BATTERY_OFF BUTTON_POWER
104 #define BATTERY_ON_TXT "SELECT - start"
105 #define BATTERY_OFF_TXT "POWER"
107 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
109 #define BATTERY_ON BUTTON_PLAY
110 #define BATTERY_OFF BUTTON_POWER
111 #define BATTERY_ON_TXT "PLAY - start"
112 #define BATTERY_OFF_TXT "POWER"
114 #elif CONFIG_KEYPAD == GIGABEAT_PAD
116 #define BATTERY_ON BUTTON_SELECT
117 #define BATTERY_OFF BUTTON_POWER
118 #define BATTERY_ON_TXT "SELECT - start"
119 #define BATTERY_OFF_TXT "POWER"
121 #elif CONFIG_KEYPAD == GIGABEAT_S_PAD
123 #define BATTERY_ON BUTTON_SELECT
124 #define BATTERY_OFF BUTTON_BACK
125 #define BATTERY_ON_TXT "SELECT - start"
126 #define BATTERY_OFF_TXT "BACK"
128 #elif CONFIG_KEYPAD == MROBE500_PAD
130 #define BATTERY_ON BUTTON_RC_PLAY
131 #define BATTERY_OFF BUTTON_POWER
132 #define BATTERY_ON_TXT "PLAY - start"
133 #define BATTERY_OFF_TXT "POWER"
135 #elif CONFIG_KEYPAD == MROBE100_PAD
137 #define BATTERY_ON BUTTON_SELECT
138 #define BATTERY_OFF BUTTON_POWER
139 #define BATTERY_ON_TXT "SELECT - start"
140 #define BATTERY_OFF_TXT "POWER"
142 #elif CONFIG_KEYPAD == IAUDIO_M3_PAD
144 #define BATTERY_ON BUTTON_PLAY
145 #define BATTERY_OFF BUTTON_REC
146 #define BATTERY_RC_ON BUTTON_RC_PLAY
147 #define BATTERY_RC_OFF BUTTON_RC_REC
148 #define BATTERY_ON_TXT "PLAY - start"
149 #define BATTERY_OFF_TXT "REC"
151 #elif CONFIG_KEYPAD == COWOND2_PAD
153 #define BATTERY_OFF BUTTON_POWER
154 #define BATTERY_OFF_TXT "POWER"
156 #elif CONFIG_KEYPAD == IAUDIO67_PAD
158 #define BATTERY_OFF BUTTON_POWER
159 #define BATTERY_OFF_TXT "POWER"
160 #define BATTERY_ON BUTTON_PLAY
161 #define BATTERY_ON_TXT "PLAY - start"
163 #error No keymap defined!
166 #ifdef HAVE_TOUCHSCREEN
168 #define BATTERY_ON BUTTON_CENTER
171 #define BATTERY_OFF BUTTON_TOPLEFT
173 #ifndef BATTERY_ON_TXT
174 #define BATTERY_ON_TXT "CENTRE - start"
176 #ifndef BATTERY_OFF_TXT
177 #define BATTERY_OFF_TXT "TOPLEFT"
181 /****************************** Plugin Entry Point ****************************/
182 static const struct plugin_api
* rb
;
183 MEM_FUNCTION_WRAPPERS(rb
);
189 enum plugin_status
plugin_start(const struct plugin_api
* api
, const void* parameter
)
197 /* Struct for battery information */
200 /* the size of the struct elements is optimised to make the struct size
204 unsigned int voltage
;
206 unsigned short flags
;
207 } bat
[BUF_SIZE
/sizeof(struct batt_info
)];
209 #define BUF_ELEMENTS (sizeof(bat)/sizeof(struct batt_info))
211 static struct thread_entry
*thread_id
;
212 static struct event_queue thread_q
;
213 static bool in_usb_mode
;
214 static unsigned int buf_idx
;
216 bool exit_tsr(bool reenter
)
219 rb
->lcd_clear_display();
220 rb
->lcd_puts_scroll(0, 0, "Batt.Bench is currently running.");
221 rb
->lcd_puts_scroll(0, 1, "Press " BATTERY_OFF_TXT
" to cancel the test");
222 #ifdef HAVE_LCD_BITMAP
223 rb
->lcd_puts_scroll(0, 2, "Anything else will resume");
227 if (rb
->button_get(true) == BATTERY_OFF
)
229 rb
->queue_post(&thread_q
, EV_EXIT
, 0);
230 rb
->thread_wait(thread_id
);
231 /* remove the thread's queue from the broadcast list */
232 rb
->queue_delete(&thread_q
);
238 #define BIT_CHARGER 0x1
239 #define BIT_CHARGING 0x2
240 #define BIT_USB_POWER 0x4
242 #define HMS(x) (x)/3600,((x)%3600)/60,((x)%3600)%60
244 /* use long for aligning */
245 unsigned long thread_stack
[THREAD_STACK_SIZE
/sizeof(long)];
247 #if CONFIG_CHARGING || defined(HAVE_USB_POWER)
248 static unsigned int charge_state(void)
250 unsigned int ret
= 0;
252 if (rb
->charger_inserted())
254 #if CONFIG_CHARGING == CHARGING_MONITOR
255 if (rb
->charging_state())
259 #ifdef HAVE_USB_POWER
260 if (rb
->usb_powered())
261 ret
|= BIT_USB_POWER
;
268 static bool flush_buffer(void)
273 /* don't access the disk when in usb mode, or when no data is available */
274 if (in_usb_mode
|| (buf_idx
== 0))
279 fd
= rb
->open(BATTERY_LOG
, O_RDWR
| O_CREAT
| O_APPEND
);
285 for (i
= 0; i
< buf_idx
; i
++)
287 secs
= bat
[i
].ticks
/HZ
;
289 "%02d:%02d:%02d, %05d, %03d%%, "
293 #if CONFIG_CHARGING == CHARGING_MONITOR
297 #ifdef HAVE_USB_POWER
302 HMS(secs
), secs
, bat
[i
].level
,
303 bat
[i
].eta
/ 60, bat
[i
].eta
% 60,
306 , (bat
[i
].flags
& BIT_CHARGER
) ? 'A' : '-'
307 #if CONFIG_CHARGING == CHARGING_MONITOR
308 , (bat
[i
].flags
& BIT_CHARGING
) ? 'C' : '-'
311 #ifdef HAVE_USB_POWER
312 , (bat
[i
].flags
& BIT_USB_POWER
) ? 'U' : '-'
326 char *exit_reason
= "unknown";
327 long sleep_time
= 60 * HZ
;
328 struct queue_event ev
;
336 /* add data to buffer */
337 if (buf_idx
< BUF_ELEMENTS
)
339 bat
[buf_idx
].ticks
= *rb
->current_tick
;
340 bat
[buf_idx
].level
= rb
->battery_level();
341 bat
[buf_idx
].eta
= rb
->battery_time();
342 bat
[buf_idx
].voltage
= rb
->battery_voltage();
343 #if CONFIG_CHARGING || defined(HAVE_USB_POWER)
344 bat
[buf_idx
].flags
= charge_state();
347 rb
->register_storage_idle_func(flush_buffer
);
350 /* What to do when the measurement buffer is full:
351 1) save our measurements to disk but waste some power doing so?
352 2) throw away measurements to save some power?
353 The choice made here is to save the measurements. It is quite unusual
354 for this to occur because it requires > 16 hours of no disk activity.
356 if (buf_idx
== BUF_ELEMENTS
) {
360 /* sleep some time until next measurement */
361 rb
->queue_wait_w_tmo(&thread_q
, &ev
, sleep_time
);
364 case SYS_USB_CONNECTED
:
366 rb
->usb_acknowledge(SYS_USB_CONNECTED_ACK
);
368 case SYS_USB_DISCONNECTED
:
370 rb
->usb_acknowledge(SYS_USB_DISCONNECTED_ACK
);
373 exit_reason
= "power off";
377 #ifdef HAVE_LCD_BITMAP
378 rb
->splash(HZ
, "Exiting battery_bench...");
380 rb
->splash(HZ
, "bench exit");
382 exit_reason
= "plugin exit";
388 /* unregister flush callback and flush to disk */
389 rb
->unregister_storage_idle_func(flush_buffer
, true);
391 /* log end of bench and exit reason */
392 fd
= rb
->open(BATTERY_LOG
, O_RDWR
| O_CREAT
| O_APPEND
);
395 rb
->fdprintf(fd
, "--Battery bench ended, reason: %s--\n", exit_reason
);
401 #ifdef HAVE_LCD_BITMAP
402 typedef void (*plcdfunc
)(int x
, int y
, const unsigned char *str
);
404 static void put_centered_str(const char* str
, plcdfunc putsxy
, int lcd_width
, int line
)
407 rb
->lcd_getstringsize(str
, &strwdt
, &strhgt
);
408 putsxy((lcd_width
- strwdt
)/2, line
*(strhgt
), str
);
416 #ifdef HAVE_LCD_BITMAP
418 const char *msgs
[] = { "Battery Benchmark","Check file", BATTERY_LOG
,
419 "for more info", BATTERY_ON_TXT
, BATTERY_OFF_TXT
" - quit" };
421 rb
->lcd_clear_display();
423 #ifdef HAVE_LCD_BITMAP
424 rb
->lcd_clear_display();
425 rb
->lcd_setfont(FONT_SYSFIXED
);
427 for (i
= 0; i
<(int)(sizeof(msgs
)/sizeof(char *)); i
++)
428 put_centered_str(msgs
[i
],rb
->lcd_putsxy
,LCD_WIDTH
,i
+1);
430 rb
->lcd_puts_scroll(0, 0, "Batt.Bench.");
431 rb
->lcd_puts_scroll(0, 1, "PLAY/STOP");
435 #ifdef HAVE_REMOTE_LCD
436 rb
->lcd_remote_clear_display();
437 put_centered_str(msgs
[0],rb
->lcd_remote_putsxy
,LCD_REMOTE_WIDTH
,0);
438 put_centered_str(msgs
[sizeof(msgs
)/sizeof(char*)-2],
439 rb
->lcd_remote_putsxy
,LCD_REMOTE_WIDTH
,1);
440 put_centered_str(msgs
[sizeof(msgs
)/sizeof(char*)-1],
441 rb
->lcd_remote_putsxy
,LCD_REMOTE_WIDTH
,2);
442 rb
->lcd_remote_update();
447 button
= rb
->button_get(true);
457 #ifdef BATTERY_RC_OFF
463 if (rb
->default_event_handler(button
) == SYS_USB_CONNECTED
)
464 return PLUGIN_USB_CONNECTED
;
468 fd
= rb
->open(BATTERY_LOG
, O_RDONLY
);
471 fd
= rb
->open(BATTERY_LOG
, O_RDWR
| O_CREAT
);
475 "This plugin will log your battery performance in a\n"
476 "file (%s) every minute.\n"
477 "To properly test your battery:\n"
478 "1) Select and playback an album. "
479 "(Be sure to be more than the player's buffer)\n"
480 "2) Set to repeat.\n"
481 "3) Let the player run completely out of battery.\n"
482 "4) Recharge and copy (or whatever you want) the txt file to "
484 "Now you can make graphs with the data of the battery log.\n"
485 "Do not enter another plugin during the test or else the "
486 "logging activity will end.\n\n"
487 "P.S: You can decide how you will make your tests.\n"
488 "Just don't open another plugin to be sure that your log "
489 "will continue.\n\n",BATTERY_LOG
);
491 "Battery bench run for %s version %s\n\n"
492 ,MODEL_NAME
,rb
->appsversion
);
495 "Battery type: %d mAh Buffer Entries: %d\n"
496 " Time:, Seconds:, Level:, Time Left:, Voltage[mV]:"
500 #if CONFIG_CHARGING == CHARGING_MONITOR
503 #ifdef HAVE_USB_POWER
507 ,rb
->global_settings
->battery_capacity
,
513 rb
->splash(HZ
/ 2, "Cannot create file!");
520 fd
= rb
->open(BATTERY_LOG
, O_RDWR
| O_APPEND
);
521 rb
->fdprintf(fd
, "\n--File already present. Resuming Benchmark--\n");
523 "Battery bench run for %s version %s\n\n"
524 ,MODEL_NAME
,rb
->appsversion
);
528 rb
->queue_init(&thread_q
, true); /* put the thread's queue in the bcast list */
529 if ((thread_id
= rb
->create_thread(thread
, thread_stack
,
530 sizeof(thread_stack
), 0, "Battery Benchmark"
531 IF_PRIO(, PRIORITY_BACKGROUND
)
532 IF_COP(, CPU
))) == NULL
)
534 rb
->splash(HZ
, "Cannot create thread!");
538 rb
->plugin_tsr(exit_tsr
);
543 #endif /* SIMULATOR */