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"
131 #elif CONFIG_KEYPAD == MROBE100_PAD
133 #define BATTERY_ON BUTTON_SELECT
134 #define BATTERY_OFF BUTTON_POWER
135 #define BATTERY_ON_TXT "SELECT - start"
136 #define BATTERY_OFF_TXT "POWER - quit"
138 #elif CONFIG_KEYPAD == IAUDIO_M3_PAD
140 #define BATTERY_ON BUTTON_PLAY
141 #define BATTERY_OFF BUTTON_REC
142 #define BATTERY_RC_ON BUTTON_RC_PLAY
143 #define BATTERY_RC_OFF BUTTON_RC_REC
144 #define BATTERY_ON_TXT "PLAY - start"
145 #define BATTERY_OFF_TXT "REC - quit"
147 #elif CONFIG_KEYPAD == COWOND2_PAD
149 #define BATTERY_ON BUTTON_MENU
150 #define BATTERY_OFF BUTTON_POWER
151 #define BATTERY_ON_TXT "MENU - start"
152 #define BATTERY_OFF_TXT "POWER - quit"
155 #error No keymap defined!
159 /****************************** Plugin Entry Point ****************************/
160 static struct plugin_api
* rb
;
161 MEM_FUNCTION_WRAPPERS(rb
);
167 enum plugin_status
plugin_start(struct plugin_api
* api
, void* parameter
)
175 /* Struct for battery information */
178 /* the size of the struct elements is optimised to make the struct size
182 unsigned int voltage
;
184 unsigned short flags
;
185 } bat
[BUF_SIZE
/sizeof(struct batt_info
)];
187 struct thread_entry
*thread_id
;
188 struct event_queue thread_q
;
190 bool exit_tsr(bool reenter
)
194 rb
->lcd_clear_display();
195 rb
->lcd_puts_scroll(0, 0, "Batt.Bench is currently running.");
196 rb
->lcd_puts_scroll(0, 1, "Press OFF to cancel the test");
197 #ifdef HAVE_LCD_BITMAP
198 rb
->lcd_puts_scroll(0, 2, "Anything else will resume");
202 if (rb
->button_get(true) != BATTERY_OFF
)
206 rb
->queue_post(&thread_q
, EV_EXIT
, 0);
207 rb
->thread_wait(thread_id
);
208 /* remove the thread's queue from the broadcast list */
209 rb
->queue_delete(&thread_q
);
215 #define BIT_CHARGER 0x1
216 #define BIT_CHARGING 0x2
217 #define BIT_USB_POWER 0x4
219 #define HMS(x) (x)/3600,((x)%3600)/60,((x)%3600)%60
221 /* use long for aligning */
222 unsigned long thread_stack
[THREAD_STACK_SIZE
/sizeof(long)];
224 #if CONFIG_CHARGING || defined(HAVE_USB_POWER)
225 unsigned int charge_state(void)
227 unsigned int ret
= 0;
229 if(rb
->charger_inserted())
231 #if CONFIG_CHARGING == CHARGING_MONITOR
232 if(rb
->charging_state())
236 #ifdef HAVE_USB_POWER
237 if(rb
->usb_powered())
238 ret
|= BIT_USB_POWER
;
246 bool got_info
= false, timeflag
= false, in_usb_mode
= false;
247 int fd
, buffelements
, tick
= 1, i
= 0, skipped
= 0, exit
= 0;
248 int fst
= 0, lst
= 0; /* first and last skipped tick */
249 unsigned int last_voltage
= 0;
250 #if CONFIG_CHARGING || defined(HAVE_USB_POWER)
251 unsigned int last_state
= 0;
253 long sleep_time
= 5 * HZ
;
255 struct queue_event ev
;
257 buffelements
= sizeof(bat
)/sizeof(struct batt_info
);
259 #ifndef HAVE_FLASH_STORAGE
260 if(rb
->global_settings
->disk_spindown
> 1)
261 sleep_time
= (rb
->global_settings
->disk_spindown
- 1) * HZ
;
266 if(!in_usb_mode
&& got_info
&&
267 (exit
|| timeflag
|| rb
->ata_disk_is_active()) )
269 int last
, secs
, j
, temp
= skipped
;
271 fd
= rb
->open(BATTERY_LOG
, O_RDWR
| O_CREAT
| O_APPEND
);
283 rb
->fdprintf(fd
,"-Skipped %d measurements from "
284 "%02d:%02d:%02d to %02d:%02d:%02d-\n",skipped
,
294 for(j
= i
; j
< last
; j
++)
296 secs
= bat
[j
].ticks
/HZ
;
298 "%02d:%02d:%02d, %05d, %03d%%, "
299 "%02d:%02d, %04d, %04d"
302 #if CONFIG_CHARGING == CHARGING_MONITOR
306 #ifdef HAVE_USB_POWER
311 HMS(secs
), secs
, bat
[j
].level
,
312 bat
[j
].eta
/ 60, bat
[j
].eta
% 60,
316 ,(bat
[j
].flags
& BIT_CHARGER
)?'A':'-'
317 #if CONFIG_CHARGING == CHARGING_MONITOR
318 ,(bat
[j
].flags
& BIT_CHARGING
)?'C':'-'
321 #ifdef HAVE_USB_POWER
322 ,(bat
[j
].flags
& BIT_USB_POWER
)?'U':'-'
326 if(!j
% 100 && !j
) /* yield() at every 100 writes */
334 tick
= *rb
->current_tick
;
341 unsigned int current_voltage
;
343 #if CONFIG_CODEC == SWCODEC
344 !rb
->pcm_is_playing()
346 !rb
->mp3_is_playing()
348 && (*rb
->current_tick
- tick
) > DISK_SPINDOWN_TIMEOUT
* HZ
)
351 if(last_voltage
!= (current_voltage
=rb
->battery_voltage())
352 #if CONFIG_CHARGING || defined(HAVE_USB_POWER)
353 || last_state
!= charge_state()
357 if(i
== buffelements
)
368 bat
[i
].ticks
= *rb
->current_tick
;
369 bat
[i
].level
= rb
->battery_level();
370 bat
[i
].eta
= rb
->battery_time();
371 last_voltage
= bat
[i
].voltage
= current_voltage
;
372 #if CONFIG_CHARGING || defined(HAVE_USB_POWER)
373 bat
[i
].flags
= last_state
= charge_state();
385 #ifdef HAVE_LCD_BITMAP
386 "Exiting battery_bench...");
393 rb
->queue_wait_w_tmo(&thread_q
, &ev
, sleep_time
);
396 case SYS_USB_CONNECTED
:
398 rb
->usb_acknowledge(SYS_USB_CONNECTED_ACK
);
400 case SYS_USB_DISCONNECTED
:
402 rb
->usb_acknowledge(SYS_USB_DISCONNECTED_ACK
);
415 #ifdef HAVE_LCD_BITMAP
416 typedef void (*plcdfunc
)(int x
, int y
, const unsigned char *str
);
418 void put_centered_str(const char* str
, plcdfunc putsxy
, int lcd_width
, int line
)
421 rb
->lcd_getstringsize(str
, &strwdt
, &strhgt
);
422 putsxy((lcd_width
- strwdt
)/2, line
*(strhgt
), str
);
430 #ifdef HAVE_LCD_BITMAP
432 const char *msgs
[] = { "Battery Benchmark","Check file", BATTERY_LOG
,
433 "for more info", BATTERY_ON_TXT
, BATTERY_OFF_TXT
};
435 rb
->lcd_clear_display();
437 #ifdef HAVE_LCD_BITMAP
438 rb
->lcd_clear_display();
439 rb
->lcd_setfont(FONT_SYSFIXED
);
441 for(i
= 0; i
<(int)(sizeof(msgs
)/sizeof(char *)); i
++)
442 put_centered_str(msgs
[i
],rb
->lcd_putsxy
,LCD_WIDTH
,i
+1);
444 rb
->lcd_puts_scroll(0, 0, "Batt.Bench.");
445 rb
->lcd_puts_scroll(0, 1, "PLAY/STOP");
449 #ifdef HAVE_REMOTE_LCD
450 rb
->lcd_remote_clear_display();
451 put_centered_str(msgs
[0],rb
->lcd_remote_putsxy
,LCD_REMOTE_WIDTH
,0);
452 put_centered_str(msgs
[sizeof(msgs
)/sizeof(char*)-2],
453 rb
->lcd_remote_putsxy
,LCD_REMOTE_WIDTH
,1);
454 put_centered_str(msgs
[sizeof(msgs
)/sizeof(char*)-1],
455 rb
->lcd_remote_putsxy
,LCD_REMOTE_WIDTH
,2);
456 rb
->lcd_remote_update();
461 button
= rb
->button_get(true);
471 #ifdef BATTERY_RC_OFF
476 default: if(rb
->default_event_handler(button
) == SYS_USB_CONNECTED
)
477 return PLUGIN_USB_CONNECTED
;
481 fd
= rb
->open(BATTERY_LOG
, O_RDONLY
);
484 fd
= rb
->open(BATTERY_LOG
, O_RDWR
| O_CREAT
);
488 "This plugin will log your battery performance in a\n"
489 "file (%s) every time the disk is accessed (or every hour).\n"
490 "To properly test your battery:\n"
491 "1) Select and playback an album. "
492 "(Be sure to be more than the player's buffer)\n"
493 "2) Set to repeat.\n"
494 "3) Let the player run completely out of battery.\n"
495 "4) Recharge and copy (or whatever you want) the txt file to "
497 "Now you can make graphs with the data of the battery log.\n"
498 "Do not enter another plugin during the test or else the "
499 "logging activity will end.\n\n"
500 "P.S: You can decide how you will make your tests.\n"
501 "Just don't open another plugin to be sure that your log "
503 "M/DA (Measurements per Disk Activity) shows how many times\n"
504 "data was logged in the buffer between Disk Activity.\n\n"
505 "Battery type: %d mAh Buffer Entries: %d\n"
506 " Time:, Seconds:, Level:, Time Left:, Voltage[mV]:,"
511 #if CONFIG_CHARGING == CHARGING_MONITOR
514 #ifdef HAVE_USB_POWER
518 ,BATTERY_LOG
,rb
->global_settings
->battery_capacity
,
519 BUF_SIZE
/ (unsigned)sizeof(struct batt_info
));
524 rb
->splash(HZ
/ 2, "Cannot create file!");
531 fd
= rb
->open(BATTERY_LOG
, O_RDWR
| O_APPEND
);
532 rb
->fdprintf(fd
, "\n--File already present. Resuming Benchmark--\n");
536 rb
->queue_init(&thread_q
, true); /* put the thread's queue in the bcast list */
537 if((thread_id
= rb
->create_thread(thread
, thread_stack
,
538 sizeof(thread_stack
), 0, "Battery Benchmark"
539 IF_PRIO(, PRIORITY_BACKGROUND
)
540 IF_COP(, CPU
))) == NULL
)
542 rb
->splash(HZ
, "Cannot create thread!");
546 rb
->plugin_tsr(exit_tsr
);