1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
11 * Copyright (C) 2006 Alexander Spyridakis, Hristo Kovachev
13 * All files in this archive are subject to the GNU General Public License.
14 * See the file COPYING in the source tree root for full license agreement.
16 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
17 * KIND, either express or implied.
19 ****************************************************************************/
20 #ifndef SIMULATOR /* not for the simulator */
25 #define BATTERY_LOG "/battery_bench.txt"
26 #define BUF_SIZE 16000
27 #define DISK_SPINDOWN_TIMEOUT 3600
31 /* seems to work with 1300, but who knows... */
32 #define THREAD_STACK_SIZE DEFAULT_STACK_SIZE + 0x200
34 #if CONFIG_KEYPAD == RECORDER_PAD
36 #define BATTERY_ON BUTTON_PLAY
37 #define BATTERY_OFF BUTTON_OFF
38 #define BATTERY_ON_TXT "PLAY - start"
39 #define BATTERY_OFF_TXT "OFF - quit"
41 #if BUTTON_REMOTE != 0
42 #define BATTERY_RC_ON BUTTON_RC_PLAY
43 #define BATTERY_RC_OFF BUTTON_RC_STOP
46 #elif CONFIG_KEYPAD == ONDIO_PAD
48 #define BATTERY_ON BUTTON_RIGHT
49 #define BATTERY_OFF BUTTON_OFF
50 #define BATTERY_ON_TXT "RIGHT - start"
51 #define BATTERY_OFF_TXT "OFF - quit"
53 #elif CONFIG_KEYPAD == PLAYER_PAD
55 #define BATTERY_ON BUTTON_PLAY
56 #define BATTERY_OFF BUTTON_STOP
58 #define BATTERY_RC_ON BUTTON_RC_PLAY
59 #define BATTERY_RC_OFF BUTTON_RC_STOP
61 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
62 (CONFIG_KEYPAD == IRIVER_H300_PAD)
64 #define BATTERY_ON BUTTON_ON
65 #define BATTERY_RC_ON BUTTON_RC_ON
67 #define BATTERY_OFF BUTTON_OFF
68 #define BATTERY_RC_OFF BUTTON_RC_STOP
70 #define BATTERY_ON_TXT "PLAY - start"
71 #define BATTERY_OFF_TXT "STOP - quit"
73 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
74 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
75 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
77 #define BATTERY_ON BUTTON_PLAY
78 #define BATTERY_OFF BUTTON_MENU
79 #define BATTERY_ON_TXT "PLAY - start"
80 #define BATTERY_OFF_TXT "MENU - quit"
82 #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
84 #define BATTERY_ON BUTTON_SELECT
85 #define BATTERY_OFF BUTTON_POWER
86 #define BATTERY_ON_TXT "SELECT - start"
87 #define BATTERY_OFF_TXT "POWER - quit"
89 #elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD
91 #define BATTERY_ON BUTTON_SELECT
92 #define BATTERY_OFF BUTTON_PLAY
93 #define BATTERY_ON_TXT "SELECT - start"
94 #define BATTERY_OFF_TXT "PLAY - quit"
96 #elif (CONFIG_KEYPAD == SANSA_E200_PAD) || \
97 (CONFIG_KEYPAD == SANSA_C200_PAD)
98 #define BATTERY_ON BUTTON_SELECT
99 #define BATTERY_OFF BUTTON_POWER
100 #define BATTERY_ON_TXT "SELECT - start"
101 #define BATTERY_OFF_TXT "POWER - quit"
103 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
105 #define BATTERY_ON BUTTON_PLAY
106 #define BATTERY_OFF BUTTON_POWER
107 #define BATTERY_ON_TXT "PLAY - start"
108 #define BATTERY_OFF_TXT "POWER - quit"
110 #elif CONFIG_KEYPAD == GIGABEAT_PAD
112 #define BATTERY_ON BUTTON_SELECT
113 #define BATTERY_OFF BUTTON_POWER
114 #define BATTERY_ON_TXT "SELECT - start"
115 #define BATTERY_OFF_TXT "POWER - quit"
117 #elif CONFIG_KEYPAD == GIGABEAT_S_PAD
119 #define BATTERY_ON BUTTON_SELECT
120 #define BATTERY_OFF BUTTON_BACK
121 #define BATTERY_ON_TXT "SELECT - start"
122 #define BATTERY_OFF_TXT "BACK - quit"
124 #elif CONFIG_KEYPAD == MROBE500_PAD
126 #define BATTERY_ON BUTTON_RC_PLAY
127 #define BATTERY_OFF BUTTON_POWER
128 #define BATTERY_ON_TXT "PLAY - start"
129 #define BATTERY_OFF_TXT "POWER - quit"
134 /****************************** Plugin Entry Point ****************************/
135 static struct plugin_api
* rb
;
136 MEM_FUNCTION_WRAPPERS(rb
);
142 enum plugin_status
plugin_start(struct plugin_api
* api
, void* parameter
)
150 /* Struct for battery information */
153 /* the size of the struct elements is optimised to make the struct size
157 unsigned int voltage
;
159 unsigned short flags
;
160 } bat
[BUF_SIZE
/sizeof(struct batt_info
)];
162 struct thread_entry
*thread_id
;
163 struct event_queue thread_q
;
165 bool exit_tsr(bool reenter
)
169 rb
->lcd_clear_display();
170 rb
->lcd_puts_scroll(0, 0, "Batt.Bench is currently running.");
171 rb
->lcd_puts_scroll(0, 1, "Press OFF to cancel the test");
172 #ifdef HAVE_LCD_BITMAP
173 rb
->lcd_puts_scroll(0, 2, "Anything else will resume");
177 if (rb
->button_get(true) != BATTERY_OFF
)
181 rb
->queue_post(&thread_q
, EV_EXIT
, 0);
182 rb
->thread_wait(thread_id
);
183 /* remove the thread's queue from the broadcast list */
184 rb
->queue_delete(&thread_q
);
190 #define BIT_CHARGER 0x1
191 #define BIT_CHARGING 0x2
192 #define BIT_USB_POWER 0x4
194 #define HMS(x) (x)/3600,((x)%3600)/60,((x)%3600)%60
196 /* use long for aligning */
197 unsigned long thread_stack
[THREAD_STACK_SIZE
/sizeof(long)];
199 #if CONFIG_CHARGING || defined(HAVE_USB_POWER)
200 unsigned int charge_state(void)
202 unsigned int ret
= 0;
204 if(rb
->charger_inserted())
206 #if CONFIG_CHARGING == CHARGING_MONITOR
207 if(rb
->charging_state())
211 #ifdef HAVE_USB_POWER
212 if(rb
->usb_powered())
213 ret
|= BIT_USB_POWER
;
221 bool got_info
= false, timeflag
= false, in_usb_mode
= false;
222 int fd
, buffelements
, tick
= 1, i
= 0, skipped
= 0, exit
= 0;
223 int fst
= 0, lst
= 0; /* first and last skipped tick */
224 unsigned int last_voltage
= 0;
225 #if CONFIG_CHARGING || defined(HAVE_USB_POWER)
226 unsigned int last_state
= 0;
228 long sleep_time
= 5 * HZ
;
230 struct queue_event ev
;
232 buffelements
= sizeof(bat
)/sizeof(struct batt_info
);
234 #ifndef HAVE_FLASH_STORAGE
235 if(rb
->global_settings
->disk_spindown
> 1)
236 sleep_time
= (rb
->global_settings
->disk_spindown
- 1) * HZ
;
241 if(!in_usb_mode
&& got_info
&&
242 (exit
|| timeflag
|| rb
->ata_disk_is_active()) )
244 int last
, secs
, j
, temp
= skipped
;
246 fd
= rb
->open(BATTERY_LOG
, O_RDWR
| O_CREAT
| O_APPEND
);
258 rb
->fdprintf(fd
,"-Skipped %d measurements from "
259 "%02d:%02d:%02d to %02d:%02d:%02d-\n",skipped
,
269 for(j
= i
; j
< last
; j
++)
271 secs
= bat
[j
].ticks
/HZ
;
273 "%02d:%02d:%02d, %05d, %03d%%, "
274 "%02d:%02d, %04d, %04d"
277 #if CONFIG_CHARGING == CHARGING_MONITOR
281 #ifdef HAVE_USB_POWER
286 HMS(secs
), secs
, bat
[j
].level
,
287 bat
[j
].eta
/ 60, bat
[j
].eta
% 60,
291 ,(bat
[j
].flags
& BIT_CHARGER
)?'A':'-'
292 #if CONFIG_CHARGING == CHARGING_MONITOR
293 ,(bat
[j
].flags
& BIT_CHARGING
)?'C':'-'
296 #ifdef HAVE_USB_POWER
297 ,(bat
[j
].flags
& BIT_USB_POWER
)?'U':'-'
301 if(!j
% 100 && !j
) /* yield() at every 100 writes */
309 tick
= *rb
->current_tick
;
316 unsigned int current_voltage
;
318 #if CONFIG_CODEC == SWCODEC
319 !rb
->pcm_is_playing()
321 !rb
->mp3_is_playing()
323 && (*rb
->current_tick
- tick
) > DISK_SPINDOWN_TIMEOUT
* HZ
)
326 if(last_voltage
!= (current_voltage
=rb
->battery_voltage())
327 #if CONFIG_CHARGING || defined(HAVE_USB_POWER)
328 || last_state
!= charge_state()
332 if(i
== buffelements
)
343 bat
[i
].ticks
= *rb
->current_tick
;
344 bat
[i
].level
= rb
->battery_level();
345 bat
[i
].eta
= rb
->battery_time();
346 last_voltage
= bat
[i
].voltage
= current_voltage
;
347 #if CONFIG_CHARGING || defined(HAVE_USB_POWER)
348 bat
[i
].flags
= last_state
= charge_state();
360 #ifdef HAVE_LCD_BITMAP
361 "Exiting battery_bench...");
368 rb
->queue_wait_w_tmo(&thread_q
, &ev
, sleep_time
);
371 case SYS_USB_CONNECTED
:
373 rb
->usb_acknowledge(SYS_USB_CONNECTED_ACK
);
375 case SYS_USB_DISCONNECTED
:
377 rb
->usb_acknowledge(SYS_USB_DISCONNECTED_ACK
);
390 #ifdef HAVE_LCD_BITMAP
391 typedef void (*plcdfunc
)(int x
, int y
, const unsigned char *str
);
393 void put_centered_str(const char* str
, plcdfunc putsxy
, int lcd_width
, int line
)
396 rb
->lcd_getstringsize(str
, &strwdt
, &strhgt
);
397 putsxy((lcd_width
- strwdt
)/2, line
*(strhgt
), str
);
405 #ifdef HAVE_LCD_BITMAP
407 const char *msgs
[] = { "Battery Benchmark","Check file", BATTERY_LOG
,
408 "for more info", BATTERY_ON_TXT
, BATTERY_OFF_TXT
};
410 rb
->lcd_clear_display();
412 #ifdef HAVE_LCD_BITMAP
413 rb
->lcd_clear_display();
414 rb
->lcd_setfont(FONT_SYSFIXED
);
416 for(i
= 0; i
<(int)(sizeof(msgs
)/sizeof(char *)); i
++)
417 put_centered_str(msgs
[i
],rb
->lcd_putsxy
,LCD_WIDTH
,i
+1);
419 rb
->lcd_puts_scroll(0, 0, "Batt.Bench.");
420 rb
->lcd_puts_scroll(0, 1, "PLAY/STOP");
424 #ifdef HAVE_REMOTE_LCD
425 rb
->lcd_remote_clear_display();
426 put_centered_str(msgs
[0],rb
->lcd_remote_putsxy
,LCD_REMOTE_WIDTH
,0);
427 put_centered_str(msgs
[sizeof(msgs
)/sizeof(char*)-2],
428 rb
->lcd_remote_putsxy
,LCD_REMOTE_WIDTH
,1);
429 put_centered_str(msgs
[sizeof(msgs
)/sizeof(char*)-1],
430 rb
->lcd_remote_putsxy
,LCD_REMOTE_WIDTH
,2);
431 rb
->lcd_remote_update();
436 button
= rb
->button_get(true);
446 #ifdef BATTERY_RC_OFF
451 default: if(rb
->default_event_handler(button
) == SYS_USB_CONNECTED
)
452 return PLUGIN_USB_CONNECTED
;
456 fd
= rb
->open(BATTERY_LOG
, O_RDONLY
);
459 fd
= rb
->open(BATTERY_LOG
, O_RDWR
| O_CREAT
);
463 "This plugin will log your battery performance in a\n"
464 "file (%s) every time the disk is accessed (or every hour).\n"
465 "To properly test your battery:\n"
466 "1) Select and playback an album. "
467 "(Be sure to be more than the player's buffer)\n"
468 "2) Set to repeat.\n"
469 "3) Let the player run completely out of battery.\n"
470 "4) Recharge and copy (or whatever you want) the txt file to "
472 "Now you can make graphs with the data of the battery log.\n"
473 "Do not enter another plugin during the test or else the "
474 "logging activity will end.\n\n"
475 "P.S: You can decide how you will make your tests.\n"
476 "Just don't open another plugin to be sure that your log "
478 "M/DA (Measurements per Disk Activity) shows how many times\n"
479 "data was logged in the buffer between Disk Activity.\n\n"
480 "Battery type: %d mAh Buffer Entries: %d\n"
481 " Time:, Seconds:, Level:, Time Left:, Voltage[mV]:,"
486 #if CONFIG_CHARGING == CHARGING_MONITOR
489 #ifdef HAVE_USB_POWER
493 ,BATTERY_LOG
,rb
->global_settings
->battery_capacity
,
494 BUF_SIZE
/ (unsigned)sizeof(struct batt_info
));
499 rb
->splash(HZ
/ 2, "Cannot create file!");
506 fd
= rb
->open(BATTERY_LOG
, O_RDWR
| O_APPEND
);
507 rb
->fdprintf(fd
, "\n--File already present. Resuming Benchmark--\n");
511 rb
->queue_init(&thread_q
, true); /* put the thread's queue in the bcast list */
512 if((thread_id
= rb
->create_thread(thread
, thread_stack
,
513 sizeof(thread_stack
), 0, "Battery Benchmark"
514 IF_PRIO(, PRIORITY_BACKGROUND
)
515 IF_COP(, CPU
))) == NULL
)
517 rb
->splash(HZ
, "Cannot create thread!");
521 rb
->plugin_tsr(exit_tsr
);