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 (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"
173 #error No keymap defined!
176 #ifdef HAVE_TOUCHSCREEN
178 #define BATTERY_ON BUTTON_CENTER
181 #define BATTERY_OFF BUTTON_TOPLEFT
183 #ifndef BATTERY_ON_TXT
184 #define BATTERY_ON_TXT "CENTRE - start"
186 #ifndef BATTERY_OFF_TXT
187 #define BATTERY_OFF_TXT "TOPLEFT"
191 /****************************** Plugin Entry Point ****************************/
192 static const struct plugin_api
* rb
;
193 MEM_FUNCTION_WRAPPERS(rb
);
199 enum plugin_status
plugin_start(const struct plugin_api
* api
, const void* parameter
)
207 /* Struct for battery information */
210 /* the size of the struct elements is optimised to make the struct size
214 unsigned int voltage
;
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
)
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");
240 button
= rb
->button_get(true);
241 if (IS_SYSEVENT(button
))
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
);
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;
269 if (rb
->charger_inserted())
271 #if CONFIG_CHARGING == CHARGING_MONITOR
272 if (rb
->charging_state())
276 #ifdef HAVE_USB_POWER
277 if (rb
->usb_powered())
278 ret
|= BIT_USB_POWER
;
285 static bool flush_buffer(void)
290 /* don't access the disk when in usb mode, or when no data is available */
291 if (in_usb_mode
|| (buf_idx
== 0))
296 fd
= rb
->open(BATTERY_LOG
, O_RDWR
| O_CREAT
| O_APPEND
);
302 for (i
= 0; i
< buf_idx
; i
++)
304 secs
= bat
[i
].ticks
/HZ
;
306 "%02d:%02d:%02d, %05d, %03d%%, "
310 #if CONFIG_CHARGING == CHARGING_MONITOR
314 #ifdef HAVE_USB_POWER
319 HMS(secs
), secs
, bat
[i
].level
,
320 bat
[i
].eta
/ 60, bat
[i
].eta
% 60,
323 , (bat
[i
].flags
& BIT_CHARGER
) ? 'A' : '-'
324 #if CONFIG_CHARGING == CHARGING_MONITOR
325 , (bat
[i
].flags
& BIT_CHARGING
) ? 'C' : '-'
328 #ifdef HAVE_USB_POWER
329 , (bat
[i
].flags
& BIT_USB_POWER
) ? 'U' : '-'
343 char *exit_reason
= "unknown";
344 long sleep_time
= 60 * HZ
;
345 struct queue_event ev
;
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();
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
) {
377 /* sleep some time until next measurement */
378 rb
->queue_wait_w_tmo(&thread_q
, &ev
, sleep_time
);
381 case SYS_USB_CONNECTED
:
383 rb
->usb_acknowledge(SYS_USB_CONNECTED_ACK
);
385 case SYS_USB_DISCONNECTED
:
387 rb
->usb_acknowledge(SYS_USB_DISCONNECTED_ACK
);
390 exit_reason
= "power off";
394 #ifdef HAVE_LCD_BITMAP
395 rb
->splash(HZ
, "Exiting battery_bench...");
397 rb
->splash(HZ
, "bench exit");
399 exit_reason
= "plugin exit";
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
);
412 rb
->fdprintf(fd
, "--Battery bench ended, reason: %s--\n", exit_reason
);
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
)
424 rb
->lcd_getstringsize(str
, &strwdt
, &strhgt
);
425 putsxy((lcd_width
- strwdt
)/2, line
*(strhgt
), str
);
433 #ifdef HAVE_LCD_BITMAP
435 const char *msgs
[] = { "Battery Benchmark","Check file", BATTERY_LOG
,
436 "for more info", BATTERY_ON_TXT
, BATTERY_OFF_TXT
" - quit" };
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);
447 rb
->lcd_puts_scroll(0, 0, "Batt.Bench.");
448 rb
->lcd_puts_scroll(0, 1, "PLAY/STOP");
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();
464 button
= rb
->button_get(true);
474 #ifdef BATTERY_RC_OFF
480 if (rb
->default_event_handler(button
) == SYS_USB_CONNECTED
)
481 return PLUGIN_USB_CONNECTED
;
485 fd
= rb
->open(BATTERY_LOG
, O_RDONLY
);
488 fd
= rb
->open(BATTERY_LOG
, O_RDWR
| O_CREAT
);
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 "
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
);
508 "Battery bench run for %s version %s\n\n"
509 ,MODEL_NAME
,rb
->appsversion
);
512 "Battery type: %d mAh Buffer Entries: %d\n"
513 " Time:, Seconds:, Level:, Time Left:, Voltage[mV]:"
517 #if CONFIG_CHARGING == CHARGING_MONITOR
520 #ifdef HAVE_USB_POWER
524 ,rb
->global_settings
->battery_capacity
,
530 rb
->splash(HZ
/ 2, "Cannot create file!");
537 fd
= rb
->open(BATTERY_LOG
, O_RDWR
| O_APPEND
);
538 rb
->fdprintf(fd
, "\n--File already present. Resuming Benchmark--\n");
540 "Battery bench run for %s version %s\n\n"
541 ,MODEL_NAME
,rb
->appsversion
);
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!");
555 rb
->plugin_tsr(exit_tsr
);
560 #endif /* SIMULATOR */