Add deployment script for Theme Editor.
[kugel-rb.git] / apps / plugins / battery_bench.c
blobe6efd38d96aaeaff6dce4fdb9ea58c3e99715a08
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
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 ****************************************************************************/
23 #include "version.h"
24 #include "plugin.h"
25 PLUGIN_HEADER
27 #define BATTERY_LOG "/battery_bench.txt"
28 #define BUF_SIZE 16000
30 #define EV_EXIT 1337
32 /* seems to work with 1300, but who knows... */
33 #define THREAD_STACK_SIZE DEFAULT_STACK_SIZE + 0x200
35 #if CONFIG_KEYPAD == RECORDER_PAD
37 #define BATTERY_ON BUTTON_PLAY
38 #define BATTERY_OFF BUTTON_OFF
39 #define BATTERY_ON_TXT "PLAY - start"
40 #define BATTERY_OFF_TXT "OFF"
42 #if BUTTON_REMOTE != 0
43 #define BATTERY_RC_ON BUTTON_RC_PLAY
44 #define BATTERY_RC_OFF BUTTON_RC_STOP
45 #endif
47 #elif CONFIG_KEYPAD == ONDIO_PAD
49 #define BATTERY_ON BUTTON_RIGHT
50 #define BATTERY_OFF BUTTON_OFF
51 #define BATTERY_ON_TXT "RIGHT - start"
52 #define BATTERY_OFF_TXT "OFF"
54 #elif CONFIG_KEYPAD == PLAYER_PAD
56 #define BATTERY_ON BUTTON_PLAY
57 #define BATTERY_OFF BUTTON_STOP
58 #define BATTERY_ON_TXT "PLAY - start"
59 #define BATTERY_OFF_TXT "STOP"
61 #define BATTERY_RC_ON BUTTON_RC_PLAY
62 #define BATTERY_RC_OFF BUTTON_RC_STOP
64 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
65 (CONFIG_KEYPAD == IRIVER_H300_PAD)
67 #define BATTERY_ON BUTTON_ON
68 #define BATTERY_RC_ON BUTTON_RC_ON
70 #define BATTERY_OFF BUTTON_OFF
71 #define BATTERY_RC_OFF BUTTON_RC_STOP
73 #define BATTERY_ON_TXT "PLAY - start"
74 #define BATTERY_OFF_TXT "STOP"
76 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
77 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
78 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
80 #define BATTERY_ON BUTTON_PLAY
81 #define BATTERY_OFF BUTTON_MENU
82 #define BATTERY_ON_TXT "PLAY - start"
83 #define BATTERY_OFF_TXT "MENU"
85 #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
87 #define BATTERY_ON BUTTON_SELECT
88 #define BATTERY_OFF BUTTON_POWER
89 #define BATTERY_ON_TXT "SELECT - start"
90 #define BATTERY_OFF_TXT "POWER"
92 #elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD
94 #define BATTERY_ON BUTTON_SELECT
95 #define BATTERY_OFF BUTTON_PLAY
96 #define BATTERY_ON_TXT "SELECT - start"
97 #define BATTERY_OFF_TXT "PLAY"
99 #elif (CONFIG_KEYPAD == SANSA_E200_PAD) || \
100 (CONFIG_KEYPAD == SANSA_C200_PAD) || \
101 (CONFIG_KEYPAD == SANSA_CLIP_PAD) || \
102 (CONFIG_KEYPAD == SANSA_M200_PAD)
103 #define BATTERY_ON BUTTON_SELECT
104 #define BATTERY_OFF BUTTON_POWER
105 #define BATTERY_ON_TXT "SELECT - start"
106 #define BATTERY_OFF_TXT "POWER"
108 #elif (CONFIG_KEYPAD == SANSA_FUZE_PAD)
109 #define BATTERY_ON BUTTON_SELECT
110 #define BATTERY_OFF BUTTON_HOME
111 #define BATTERY_ON_TXT "SELECT - start"
112 #define BATTERY_OFF_TXT "HOME"
114 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
116 #define BATTERY_ON BUTTON_PLAY
117 #define BATTERY_OFF BUTTON_POWER
118 #define BATTERY_ON_TXT "PLAY - start"
119 #define BATTERY_OFF_TXT "POWER"
121 #elif CONFIG_KEYPAD == GIGABEAT_PAD
123 #define BATTERY_ON BUTTON_SELECT
124 #define BATTERY_OFF BUTTON_POWER
125 #define BATTERY_ON_TXT "SELECT - start"
126 #define BATTERY_OFF_TXT "POWER"
128 #elif CONFIG_KEYPAD == GIGABEAT_S_PAD
130 #define BATTERY_ON BUTTON_SELECT
131 #define BATTERY_OFF BUTTON_BACK
132 #define BATTERY_ON_TXT "SELECT - start"
133 #define BATTERY_OFF_TXT "BACK"
135 #elif CONFIG_KEYPAD == MROBE500_PAD
137 #define BATTERY_ON BUTTON_RC_PLAY
138 #define BATTERY_OFF BUTTON_POWER
139 #define BATTERY_ON_TXT "PLAY - start"
140 #define BATTERY_OFF_TXT "POWER"
142 #elif CONFIG_KEYPAD == MROBE100_PAD
144 #define BATTERY_ON BUTTON_SELECT
145 #define BATTERY_OFF BUTTON_POWER
146 #define BATTERY_ON_TXT "SELECT - start"
147 #define BATTERY_OFF_TXT "POWER"
149 #elif CONFIG_KEYPAD == IAUDIO_M3_PAD
151 #define BATTERY_ON BUTTON_PLAY
152 #define BATTERY_OFF BUTTON_REC
153 #define BATTERY_RC_ON BUTTON_RC_PLAY
154 #define BATTERY_RC_OFF BUTTON_RC_REC
155 #define BATTERY_ON_TXT "PLAY - start"
156 #define BATTERY_OFF_TXT "REC"
158 #elif CONFIG_KEYPAD == COWON_D2_PAD
160 #define BATTERY_OFF BUTTON_POWER
161 #define BATTERY_OFF_TXT "POWER"
163 #elif CONFIG_KEYPAD == IAUDIO67_PAD
165 #define BATTERY_OFF BUTTON_POWER
166 #define BATTERY_OFF_TXT "POWER"
167 #define BATTERY_ON BUTTON_PLAY
168 #define BATTERY_ON_TXT "PLAY - start"
170 #elif CONFIG_KEYPAD == CREATIVEZVM_PAD
171 #define BATTERY_ON BUTTON_PLAY
172 #define BATTERY_ON_TXT "PLAY - start"
173 #define BATTERY_OFF BUTTON_BACK
174 #define BATTERY_OFF_TXT "BACK"
176 #elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD
178 #define BATTERY_ON BUTTON_MENU
179 #define BATTERY_OFF BUTTON_POWER
180 #define BATTERY_ON_TXT "MENU - start"
181 #define BATTERY_OFF_TXT "POWER"
183 #elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD
185 #define BATTERY_ON BUTTON_MENU
186 #define BATTERY_OFF BUTTON_POWER
187 #define BATTERY_ON_TXT "MENU - start"
188 #define BATTERY_OFF_TXT "POWER"
190 #elif CONFIG_KEYPAD == ONDAVX747_PAD
192 #define BATTERY_OFF BUTTON_POWER
193 #define BATTERY_OFF_TXT "POWER"
194 #elif CONFIG_KEYPAD == ONDAVX777_PAD
196 #define BATTERY_OFF BUTTON_POWER
197 #define BATTERY_OFF_TXT "POWER"
199 #elif CONFIG_KEYPAD == SAMSUNG_YH_PAD
201 #define BATTERY_ON BUTTON_LEFT
202 #define BATTERY_OFF BUTTON_RIGHT
203 #define BATTERY_ON_TXT "LEFT"
204 #define BATTERY_OFF_TXT "RIGHT"
206 #elif CONFIG_KEYPAD == PBELL_VIBE500_PAD
208 #define BATTERY_ON BUTTON_PLAY
209 #define BATTERY_OFF BUTTON_REC
210 #define BATTERY_ON_TXT "PLAY - start"
211 #define BATTERY_OFF_TXT "REC"
213 #elif CONFIG_KEYPAD == MPIO_HD200_PAD
214 #define BATTERY_ON BUTTON_PLAY
215 #define BATTERY_OFF BUTTON_REC
216 #define BATTERY_ON_TXT "PLAY - start"
217 #define BATTERY_OFF_TXT "REC"
219 #else
220 #error No keymap defined!
221 #endif
223 #ifdef HAVE_TOUCHSCREEN
224 #ifndef BATTERY_ON
225 #define BATTERY_ON BUTTON_CENTER
226 #endif
227 #ifndef BATTERY_OFF
228 #define BATTERY_OFF BUTTON_TOPLEFT
229 #endif
230 #ifndef BATTERY_ON_TXT
231 #define BATTERY_ON_TXT "CENTRE - start"
232 #endif
233 #ifndef BATTERY_OFF_TXT
234 #define BATTERY_OFF_TXT "TOPLEFT"
235 #endif
236 #endif
238 /****************************** Plugin Entry Point ****************************/
239 int main(void);
240 bool exit_tsr(bool);
241 void thread(void);
244 enum plugin_status plugin_start(const void* parameter)
246 (void)parameter;
248 return main();
251 long start_tick;
253 /* Struct for battery information */
254 struct batt_info
256 /* the size of the struct elements is optimised to make the struct size
257 * a power of 2 */
258 unsigned secs;
259 int eta;
260 unsigned int voltage;
261 short level;
262 unsigned short flags;
263 } bat[BUF_SIZE/sizeof(struct batt_info)];
265 #define BUF_ELEMENTS (sizeof(bat)/sizeof(struct batt_info))
267 static unsigned int thread_id;
268 static struct event_queue thread_q;
269 static bool in_usb_mode;
270 static unsigned int buf_idx;
272 bool exit_tsr(bool reenter)
274 long button;
275 (void)reenter;
276 rb->lcd_clear_display();
277 rb->lcd_puts_scroll(0, 0, "Batt.Bench is currently running.");
278 rb->lcd_puts_scroll(0, 1, "Press " BATTERY_OFF_TXT " to cancel the test");
279 #ifdef HAVE_LCD_BITMAP
280 rb->lcd_puts_scroll(0, 2, "Anything else will resume");
281 #endif
282 rb->lcd_update();
284 while (1)
286 button = rb->button_get(true);
287 if (IS_SYSEVENT(button))
288 continue;
289 if (button == BATTERY_OFF)
291 rb->queue_post(&thread_q, EV_EXIT, 0);
292 rb->thread_wait(thread_id);
293 /* remove the thread's queue from the broadcast list */
294 rb->queue_delete(&thread_q);
295 return true;
297 else return false;
301 #define BIT_CHARGER 0x1
302 #define BIT_CHARGING 0x2
303 #define BIT_USB_POWER 0x4
305 #define HMS(x) (x)/3600,((x)%3600)/60,((x)%3600)%60
307 /* use long for aligning */
308 unsigned long thread_stack[THREAD_STACK_SIZE/sizeof(long)];
310 #if CONFIG_CHARGING || defined(HAVE_USB_POWER)
311 static unsigned int charge_state(void)
313 unsigned int ret = 0;
314 #if CONFIG_CHARGING
315 if (rb->charger_inserted())
316 ret = BIT_CHARGER;
317 #if CONFIG_CHARGING >= CHARGING_MONITOR
318 if (rb->charging_state())
319 ret |= BIT_CHARGING;
320 #endif
321 #endif
322 #ifdef HAVE_USB_POWER
323 if (rb->usb_powered())
324 ret |= BIT_USB_POWER;
325 #endif
326 return ret;
328 #endif
331 static void flush_buffer(void* data)
333 (void)data;
334 int fd;
335 unsigned int i;
337 /* don't access the disk when in usb mode, or when no data is available */
338 if (in_usb_mode || (buf_idx == 0))
339 return;
341 fd = rb->open(BATTERY_LOG, O_RDWR | O_CREAT | O_APPEND, 0666);
342 if (fd < 0)
343 return;
345 for (i = 0; i < buf_idx; i++)
347 rb->fdprintf(fd,
348 "%02d:%02d:%02d, %05d, %03d%%, "
349 "%02d:%02d, %04d, "
350 #if CONFIG_CHARGING
351 " %c"
352 #if CONFIG_CHARGING >= CHARGING_MONITOR
353 ", %c"
354 #endif
355 #endif
356 #ifdef HAVE_USB_POWER
357 ", %c"
358 #endif
359 "\n",
361 HMS(bat[i].secs), bat[i].secs, bat[i].level,
362 bat[i].eta / 60, bat[i].eta % 60,
363 bat[i].voltage
364 #if CONFIG_CHARGING
365 , (bat[i].flags & BIT_CHARGER) ? 'A' : '-'
366 #if CONFIG_CHARGING >= CHARGING_MONITOR
367 , (bat[i].flags & BIT_CHARGING) ? 'C' : '-'
368 #endif
369 #endif
370 #ifdef HAVE_USB_POWER
371 , (bat[i].flags & BIT_USB_POWER) ? 'U' : '-'
372 #endif
375 rb->close(fd);
377 buf_idx = 0;
381 void thread(void)
383 bool exit = false;
384 char *exit_reason = "unknown";
385 long sleep_time = 60 * HZ;
386 struct queue_event ev;
387 int fd;
389 in_usb_mode = false;
390 buf_idx = 0;
392 while (!exit)
394 /* add data to buffer */
395 if (buf_idx < BUF_ELEMENTS)
397 bat[buf_idx].secs = (*rb->current_tick - start_tick) / HZ;
398 bat[buf_idx].level = rb->battery_level();
399 bat[buf_idx].eta = rb->battery_time();
400 bat[buf_idx].voltage = rb->battery_voltage();
401 #if CONFIG_CHARGING || defined(HAVE_USB_POWER)
402 bat[buf_idx].flags = charge_state();
403 #endif
404 buf_idx++;
405 rb->register_storage_idle_func(flush_buffer);
408 /* What to do when the measurement buffer is full:
409 1) save our measurements to disk but waste some power doing so?
410 2) throw away measurements to save some power?
411 The choice made here is to save the measurements. It is quite unusual
412 for this to occur because it requires > 16 hours of no disk activity.
414 if (buf_idx == BUF_ELEMENTS) {
415 flush_buffer(NULL);
418 /* sleep some time until next measurement */
419 rb->queue_wait_w_tmo(&thread_q, &ev, sleep_time);
420 switch (ev.id)
422 case SYS_USB_CONNECTED:
423 in_usb_mode = true;
424 rb->usb_acknowledge(SYS_USB_CONNECTED_ACK);
425 break;
426 case SYS_USB_DISCONNECTED:
427 in_usb_mode = false;
428 rb->usb_acknowledge(SYS_USB_DISCONNECTED_ACK);
429 break;
430 case SYS_POWEROFF:
431 exit_reason = "power off";
432 exit = true;
433 break;
434 case EV_EXIT:
435 #ifdef HAVE_LCD_BITMAP
436 rb->splash(HZ, "Exiting battery_bench...");
437 #else
438 rb->splash(HZ, "bench exit");
439 #endif
440 exit_reason = "plugin exit";
441 exit = true;
442 break;
446 /* unregister flush callback and flush to disk */
447 rb->unregister_storage_idle_func(flush_buffer, true);
449 /* log end of bench and exit reason */
450 fd = rb->open(BATTERY_LOG, O_RDWR | O_CREAT | O_APPEND, 0666);
451 if (fd >= 0)
453 rb->fdprintf(fd, "--Battery bench ended, reason: %s--\n", exit_reason);
454 rb->close(fd);
459 #ifdef HAVE_LCD_BITMAP
460 typedef void (*plcdfunc)(int x, int y, const unsigned char *str);
462 static void put_centered_str(const char* str, plcdfunc putsxy, int lcd_width, int line)
464 int strwdt, strhgt;
465 rb->lcd_getstringsize(str, &strwdt, &strhgt);
466 putsxy((lcd_width - strwdt)/2, line*(strhgt), str);
468 #endif
470 int main(void)
472 int button, fd;
473 bool on = false;
474 start_tick = *rb->current_tick;
475 #ifdef HAVE_LCD_BITMAP
476 int i;
477 const char *msgs[] = { "Battery Benchmark","Check file", BATTERY_LOG,
478 "for more info", BATTERY_ON_TXT, BATTERY_OFF_TXT " - quit" };
479 #endif
480 rb->lcd_clear_display();
482 #ifdef HAVE_LCD_BITMAP
483 rb->lcd_clear_display();
484 rb->lcd_setfont(FONT_SYSFIXED);
486 for (i = 0; i<(int)(sizeof(msgs)/sizeof(char *)); i++)
487 put_centered_str(msgs[i],rb->lcd_putsxy,LCD_WIDTH,i+1);
488 #else
489 rb->lcd_puts_scroll(0, 0, "Batt.Bench.");
490 rb->lcd_puts_scroll(0, 1, "PLAY/STOP");
491 #endif
492 rb->lcd_update();
494 #ifdef HAVE_REMOTE_LCD
495 rb->lcd_remote_clear_display();
496 put_centered_str(msgs[0],rb->lcd_remote_putsxy,LCD_REMOTE_WIDTH,0);
497 put_centered_str(msgs[sizeof(msgs)/sizeof(char*)-2],
498 rb->lcd_remote_putsxy,LCD_REMOTE_WIDTH,1);
499 put_centered_str(msgs[sizeof(msgs)/sizeof(char*)-1],
500 rb->lcd_remote_putsxy,LCD_REMOTE_WIDTH,2);
501 rb->lcd_remote_update();
502 #endif
506 button = rb->button_get(true);
507 switch (button)
509 case BATTERY_ON:
510 #ifdef BATTERY_RC_ON
511 case BATTERY_RC_ON:
512 #endif
513 on = true;
514 break;
515 case BATTERY_OFF:
516 #ifdef BATTERY_RC_OFF
517 case BATTERY_RC_OFF:
518 #endif
519 return PLUGIN_OK;
521 default:
522 if (rb->default_event_handler(button) == SYS_USB_CONNECTED)
523 return PLUGIN_USB_CONNECTED;
525 }while(!on);
527 fd = rb->open(BATTERY_LOG, O_RDONLY);
528 if (fd < 0)
530 fd = rb->open(BATTERY_LOG, O_RDWR | O_CREAT, 0666);
531 if (fd >= 0)
533 rb->fdprintf(fd,
534 "# This plugin will log your battery performance in a\n"
535 "# file (%s) every minute.\n"
536 "# To properly test your battery:\n"
537 "# 1) Select and playback an album. "
538 "# (Be sure to be more than the player's buffer)\n"
539 "# 2) Set to repeat.\n"
540 "# 3) Let the player run completely out of battery.\n"
541 "# 4) Recharge and copy (or whatever you want) the txt file to "
542 "# your computer.\n"
543 "# Now you can make graphs with the data of the battery log.\n"
544 "# Do not enter another plugin during the test or else the \n"
545 "# logging activity will end.\n\n"
546 "# P.S: You can decide how you will make your tests.\n"
547 "# Just don't open another plugin to be sure that your log "
548 "will continue.\n\n",BATTERY_LOG);
549 rb->fdprintf(fd,
550 "# Battery bench run for %s version %s\n\n"
551 ,MODEL_NAME,rb->rbversion);
553 rb->fdprintf(fd, "# Battery type: %d mAh Buffer Entries: %d\n",
554 rb->global_settings->battery_capacity, (int)BUF_ELEMENTS);
556 rb->fdprintf(fd, "# Rockbox has been running for %02d:%02d:%02d\n",
557 HMS((unsigned)start_tick/HZ));
559 rb->fdprintf(fd,
560 "# Time:, Seconds:, Level:, Time Left:, Voltage[mV]:"
561 #if CONFIG_CHARGING
562 ", C:"
563 #endif
564 #if CONFIG_CHARGING >= CHARGING_MONITOR
565 ", S:"
566 #endif
567 #ifdef HAVE_USB_POWER
568 ", U:"
569 #endif
570 "\n");
571 rb->close(fd);
573 else
575 rb->splash(HZ / 2, "Cannot create file!");
576 return PLUGIN_ERROR;
579 else
581 rb->close(fd);
582 fd = rb->open(BATTERY_LOG, O_RDWR | O_APPEND);
583 rb->fdprintf(fd, "\n# --File already present. Resuming Benchmark--\n");
584 rb->fdprintf(fd,
585 "# Battery bench run for %s version %s\n\n"
586 ,MODEL_NAME,rb->rbversion);
587 rb->fdprintf(fd, "# Rockbox has been running for %02d:%02d:%02d\n",
588 HMS((unsigned)start_tick/HZ));
589 rb->close(fd);
592 rb->queue_init(&thread_q, true); /* put the thread's queue in the bcast list */
593 if ((thread_id = rb->create_thread(thread, thread_stack,
594 sizeof(thread_stack), 0, "Battery Benchmark"
595 IF_PRIO(, PRIORITY_BACKGROUND)
596 IF_COP(, CPU))) == 0)
598 rb->splash(HZ, "Cannot create thread!");
599 return PLUGIN_ERROR;
602 rb->plugin_tsr(exit_tsr);
604 return PLUGIN_OK;