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 */
27 #define BATTERY_LOG "/battery_bench.txt"
28 #define BUF_SIZE 16000
29 #define DISK_SPINDOWN_TIMEOUT 3600
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 - quit"
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 - quit"
55 #elif CONFIG_KEYPAD == PLAYER_PAD
57 #define BATTERY_ON BUTTON_PLAY
58 #define BATTERY_OFF BUTTON_STOP
60 #define BATTERY_RC_ON BUTTON_RC_PLAY
61 #define BATTERY_RC_OFF BUTTON_RC_STOP
63 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
64 (CONFIG_KEYPAD == IRIVER_H300_PAD)
66 #define BATTERY_ON BUTTON_ON
67 #define BATTERY_RC_ON BUTTON_RC_ON
69 #define BATTERY_OFF BUTTON_OFF
70 #define BATTERY_RC_OFF BUTTON_RC_STOP
72 #define BATTERY_ON_TXT "PLAY - start"
73 #define BATTERY_OFF_TXT "STOP - quit"
75 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
76 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
77 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
79 #define BATTERY_ON BUTTON_PLAY
80 #define BATTERY_OFF BUTTON_MENU
81 #define BATTERY_ON_TXT "PLAY - start"
82 #define BATTERY_OFF_TXT "MENU - quit"
84 #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
86 #define BATTERY_ON BUTTON_SELECT
87 #define BATTERY_OFF BUTTON_POWER
88 #define BATTERY_ON_TXT "SELECT - start"
89 #define BATTERY_OFF_TXT "POWER - quit"
91 #elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD
93 #define BATTERY_ON BUTTON_SELECT
94 #define BATTERY_OFF BUTTON_PLAY
95 #define BATTERY_ON_TXT "SELECT - start"
96 #define BATTERY_OFF_TXT "PLAY - quit"
98 #elif (CONFIG_KEYPAD == SANSA_E200_PAD) || \
99 (CONFIG_KEYPAD == SANSA_C200_PAD)
100 #define BATTERY_ON BUTTON_SELECT
101 #define BATTERY_OFF BUTTON_POWER
102 #define BATTERY_ON_TXT "SELECT - start"
103 #define BATTERY_OFF_TXT "POWER - quit"
105 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
107 #define BATTERY_ON BUTTON_PLAY
108 #define BATTERY_OFF BUTTON_POWER
109 #define BATTERY_ON_TXT "PLAY - start"
110 #define BATTERY_OFF_TXT "POWER - quit"
112 #elif CONFIG_KEYPAD == GIGABEAT_PAD
114 #define BATTERY_ON BUTTON_SELECT
115 #define BATTERY_OFF BUTTON_POWER
116 #define BATTERY_ON_TXT "SELECT - start"
117 #define BATTERY_OFF_TXT "POWER - quit"
119 #elif CONFIG_KEYPAD == GIGABEAT_S_PAD
121 #define BATTERY_ON BUTTON_SELECT
122 #define BATTERY_OFF BUTTON_BACK
123 #define BATTERY_ON_TXT "SELECT - start"
124 #define BATTERY_OFF_TXT "BACK - quit"
126 #elif CONFIG_KEYPAD == MROBE500_PAD
128 #define BATTERY_ON BUTTON_RC_PLAY
129 #define BATTERY_OFF BUTTON_POWER
130 #define BATTERY_ON_TXT "PLAY - start"
131 #define BATTERY_OFF_TXT "POWER - quit"
133 #elif CONFIG_KEYPAD == MROBE100_PAD
135 #define BATTERY_ON BUTTON_SELECT
136 #define BATTERY_OFF BUTTON_POWER
137 #define BATTERY_ON_TXT "SELECT - start"
138 #define BATTERY_OFF_TXT "POWER - quit"
140 #elif CONFIG_KEYPAD == IAUDIO_M3_PAD
142 #define BATTERY_ON BUTTON_PLAY
143 #define BATTERY_OFF BUTTON_REC
144 #define BATTERY_RC_ON BUTTON_RC_PLAY
145 #define BATTERY_RC_OFF BUTTON_RC_REC
146 #define BATTERY_ON_TXT "PLAY - start"
147 #define BATTERY_OFF_TXT "REC - quit"
149 #elif CONFIG_KEYPAD == COWOND2_PAD
151 #define BATTERY_OFF BUTTON_POWER
152 #define BATTERY_OFF_TXT "POWER - quit"
155 #error No keymap defined!
160 #define BATTERY_ON BUTTON_CENTER
163 #define BATTERY_OFF BUTTON_TOPLEFT
165 #ifndef BATTERY_ON_TXT
166 #define BATTERY_ON_TXT "CENTRE - start"
168 #ifndef BATTERY_OFF_TXT
169 #define BATTERY_OFF_TXT "TOPLEFT - quit"
173 /****************************** Plugin Entry Point ****************************/
174 static const struct plugin_api
* rb
;
175 MEM_FUNCTION_WRAPPERS(rb
);
181 enum plugin_status
plugin_start(const struct plugin_api
* api
, const void* parameter
)
189 /* Struct for battery information */
192 /* the size of the struct elements is optimised to make the struct size
196 unsigned int voltage
;
198 unsigned short flags
;
199 } bat
[BUF_SIZE
/sizeof(struct batt_info
)];
201 struct thread_entry
*thread_id
;
202 struct event_queue thread_q
;
204 bool exit_tsr(bool reenter
)
208 rb
->lcd_clear_display();
209 rb
->lcd_puts_scroll(0, 0, "Batt.Bench is currently running.");
210 rb
->lcd_puts_scroll(0, 1, "Press OFF to cancel the test");
211 #ifdef HAVE_LCD_BITMAP
212 rb
->lcd_puts_scroll(0, 2, "Anything else will resume");
216 if (rb
->button_get(true) != BATTERY_OFF
)
220 rb
->queue_post(&thread_q
, EV_EXIT
, 0);
221 rb
->thread_wait(thread_id
);
222 /* remove the thread's queue from the broadcast list */
223 rb
->queue_delete(&thread_q
);
229 #define BIT_CHARGER 0x1
230 #define BIT_CHARGING 0x2
231 #define BIT_USB_POWER 0x4
233 #define HMS(x) (x)/3600,((x)%3600)/60,((x)%3600)%60
235 /* use long for aligning */
236 unsigned long thread_stack
[THREAD_STACK_SIZE
/sizeof(long)];
238 #if CONFIG_CHARGING || defined(HAVE_USB_POWER)
239 unsigned int charge_state(void)
241 unsigned int ret
= 0;
243 if(rb
->charger_inserted())
245 #if CONFIG_CHARGING == CHARGING_MONITOR
246 if(rb
->charging_state())
250 #ifdef HAVE_USB_POWER
251 if(rb
->usb_powered())
252 ret
|= BIT_USB_POWER
;
260 bool got_info
= false, timeflag
= false, in_usb_mode
= false;
261 int fd
, buffelements
, tick
= 1, i
= 0, skipped
= 0, exit
= 0;
262 int fst
= 0, lst
= 0; /* first and last skipped tick */
263 unsigned int last_voltage
= 0;
264 #if CONFIG_CHARGING || defined(HAVE_USB_POWER)
265 unsigned int last_state
= 0;
267 long sleep_time
= 5 * HZ
;
269 struct queue_event ev
;
271 buffelements
= sizeof(bat
)/sizeof(struct batt_info
);
273 #ifndef HAVE_FLASH_STORAGE
274 if(rb
->global_settings
->disk_spindown
> 1)
275 sleep_time
= (rb
->global_settings
->disk_spindown
- 1) * HZ
;
280 if(!in_usb_mode
&& got_info
&&
281 (exit
|| timeflag
|| rb
->ata_disk_is_active()) )
283 int last
, secs
, j
, temp
= skipped
;
285 fd
= rb
->open(BATTERY_LOG
, O_RDWR
| O_CREAT
| O_APPEND
);
297 rb
->fdprintf(fd
,"-Skipped %d measurements from "
298 "%02d:%02d:%02d to %02d:%02d:%02d-\n",skipped
,
308 for(j
= i
; j
< last
; j
++)
310 secs
= bat
[j
].ticks
/HZ
;
312 "%02d:%02d:%02d, %05d, %03d%%, "
313 "%02d:%02d, %04d, %04d"
316 #if CONFIG_CHARGING == CHARGING_MONITOR
320 #ifdef HAVE_USB_POWER
325 HMS(secs
), secs
, bat
[j
].level
,
326 bat
[j
].eta
/ 60, bat
[j
].eta
% 60,
330 ,(bat
[j
].flags
& BIT_CHARGER
)?'A':'-'
331 #if CONFIG_CHARGING == CHARGING_MONITOR
332 ,(bat
[j
].flags
& BIT_CHARGING
)?'C':'-'
335 #ifdef HAVE_USB_POWER
336 ,(bat
[j
].flags
& BIT_USB_POWER
)?'U':'-'
340 if(!j
% 100 && !j
) /* yield() at every 100 writes */
348 tick
= *rb
->current_tick
;
355 unsigned int current_voltage
;
357 #if CONFIG_CODEC == SWCODEC
358 !rb
->pcm_is_playing()
360 !rb
->mp3_is_playing()
362 && (*rb
->current_tick
- tick
) > DISK_SPINDOWN_TIMEOUT
* HZ
)
365 if(last_voltage
!= (current_voltage
=rb
->battery_voltage())
366 #if CONFIG_CHARGING || defined(HAVE_USB_POWER)
367 || last_state
!= charge_state()
371 if(i
== buffelements
)
382 bat
[i
].ticks
= *rb
->current_tick
;
383 bat
[i
].level
= rb
->battery_level();
384 bat
[i
].eta
= rb
->battery_time();
385 last_voltage
= bat
[i
].voltage
= current_voltage
;
386 #if CONFIG_CHARGING || defined(HAVE_USB_POWER)
387 bat
[i
].flags
= last_state
= charge_state();
399 #ifdef HAVE_LCD_BITMAP
400 "Exiting battery_bench...");
407 rb
->queue_wait_w_tmo(&thread_q
, &ev
, sleep_time
);
410 case SYS_USB_CONNECTED
:
412 rb
->usb_acknowledge(SYS_USB_CONNECTED_ACK
);
414 case SYS_USB_DISCONNECTED
:
416 rb
->usb_acknowledge(SYS_USB_DISCONNECTED_ACK
);
429 #ifdef HAVE_LCD_BITMAP
430 typedef void (*plcdfunc
)(int x
, int y
, const unsigned char *str
);
432 void put_centered_str(const char* str
, plcdfunc putsxy
, int lcd_width
, int line
)
435 rb
->lcd_getstringsize(str
, &strwdt
, &strhgt
);
436 putsxy((lcd_width
- strwdt
)/2, line
*(strhgt
), str
);
444 #ifdef HAVE_LCD_BITMAP
446 const char *msgs
[] = { "Battery Benchmark","Check file", BATTERY_LOG
,
447 "for more info", BATTERY_ON_TXT
, BATTERY_OFF_TXT
};
449 rb
->lcd_clear_display();
451 #ifdef HAVE_LCD_BITMAP
452 rb
->lcd_clear_display();
453 rb
->lcd_setfont(FONT_SYSFIXED
);
455 for(i
= 0; i
<(int)(sizeof(msgs
)/sizeof(char *)); i
++)
456 put_centered_str(msgs
[i
],rb
->lcd_putsxy
,LCD_WIDTH
,i
+1);
458 rb
->lcd_puts_scroll(0, 0, "Batt.Bench.");
459 rb
->lcd_puts_scroll(0, 1, "PLAY/STOP");
463 #ifdef HAVE_REMOTE_LCD
464 rb
->lcd_remote_clear_display();
465 put_centered_str(msgs
[0],rb
->lcd_remote_putsxy
,LCD_REMOTE_WIDTH
,0);
466 put_centered_str(msgs
[sizeof(msgs
)/sizeof(char*)-2],
467 rb
->lcd_remote_putsxy
,LCD_REMOTE_WIDTH
,1);
468 put_centered_str(msgs
[sizeof(msgs
)/sizeof(char*)-1],
469 rb
->lcd_remote_putsxy
,LCD_REMOTE_WIDTH
,2);
470 rb
->lcd_remote_update();
475 button
= rb
->button_get(true);
485 #ifdef BATTERY_RC_OFF
490 default: if(rb
->default_event_handler(button
) == SYS_USB_CONNECTED
)
491 return PLUGIN_USB_CONNECTED
;
495 fd
= rb
->open(BATTERY_LOG
, O_RDONLY
);
498 fd
= rb
->open(BATTERY_LOG
, O_RDWR
| O_CREAT
);
502 "This plugin will log your battery performance in a\n"
503 "file (%s) every time the disk is accessed (or every hour).\n"
504 "To properly test your battery:\n"
505 "1) Select and playback an album. "
506 "(Be sure to be more than the player's buffer)\n"
507 "2) Set to repeat.\n"
508 "3) Let the player run completely out of battery.\n"
509 "4) Recharge and copy (or whatever you want) the txt file to "
511 "Now you can make graphs with the data of the battery log.\n"
512 "Do not enter another plugin during the test or else the "
513 "logging activity will end.\n\n"
514 "P.S: You can decide how you will make your tests.\n"
515 "Just don't open another plugin to be sure that your log "
517 "M/DA (Measurements per Disk Activity) shows how many times\n"
518 "data was logged in the buffer between Disk Activity.\n\n"
519 "Battery type: %d mAh Buffer Entries: %d\n"
520 " Time:, Seconds:, Level:, Time Left:, Voltage[mV]:,"
525 #if CONFIG_CHARGING == CHARGING_MONITOR
528 #ifdef HAVE_USB_POWER
532 ,BATTERY_LOG
,rb
->global_settings
->battery_capacity
,
533 BUF_SIZE
/ (unsigned)sizeof(struct batt_info
));
538 rb
->splash(HZ
/ 2, "Cannot create file!");
545 fd
= rb
->open(BATTERY_LOG
, O_RDWR
| O_APPEND
);
546 rb
->fdprintf(fd
, "\n--File already present. Resuming Benchmark--\n");
550 rb
->queue_init(&thread_q
, true); /* put the thread's queue in the bcast list */
551 if((thread_id
= rb
->create_thread(thread
, thread_stack
,
552 sizeof(thread_stack
), 0, "Battery Benchmark"
553 IF_PRIO(, PRIORITY_BACKGROUND
)
554 IF_COP(, CPU
))) == NULL
)
556 rb
->splash(HZ
, "Cannot create thread!");
560 rb
->plugin_tsr(exit_tsr
);