summaryrefslogtreecommitdiff
path: root/apps/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins')
-rw-r--r--apps/plugins/battery_bench.c281
1 files changed, 121 insertions, 160 deletions
diff --git a/apps/plugins/battery_bench.c b/apps/plugins/battery_bench.c
index 0cc028ebd0..90e9b405c8 100644
--- a/apps/plugins/battery_bench.c
+++ b/apps/plugins/battery_bench.c
@@ -26,7 +26,6 @@ PLUGIN_HEADER
26 26
27#define BATTERY_LOG "/battery_bench.txt" 27#define BATTERY_LOG "/battery_bench.txt"
28#define BUF_SIZE 16000 28#define BUF_SIZE 16000
29#define DISK_SPINDOWN_TIMEOUT 3600
30 29
31#define EV_EXIT 1337 30#define EV_EXIT 1337
32 31
@@ -198,12 +197,15 @@ struct batt_info
198 unsigned short flags; 197 unsigned short flags;
199} bat[BUF_SIZE/sizeof(struct batt_info)]; 198} bat[BUF_SIZE/sizeof(struct batt_info)];
200 199
201struct thread_entry *thread_id; 200#define BUF_ELEMENTS (sizeof(bat)/sizeof(struct batt_info))
202struct event_queue thread_q; 201
202static struct thread_entry *thread_id;
203static struct event_queue thread_q;
204static bool in_usb_mode;
205static unsigned int buf_idx;
203 206
204bool exit_tsr(bool reenter) 207bool exit_tsr(bool reenter)
205{ 208{
206 bool exit = true;
207 (void)reenter; 209 (void)reenter;
208 rb->lcd_clear_display(); 210 rb->lcd_clear_display();
209 rb->lcd_puts_scroll(0, 0, "Batt.Bench is currently running."); 211 rb->lcd_puts_scroll(0, 0, "Batt.Bench is currently running.");
@@ -213,9 +215,7 @@ bool exit_tsr(bool reenter)
213#endif 215#endif
214 rb->lcd_update(); 216 rb->lcd_update();
215 217
216 if (rb->button_get(true) != BATTERY_OFF) 218 if (rb->button_get(true) == BATTERY_OFF)
217 exit = false;
218 if (exit)
219 { 219 {
220 rb->queue_post(&thread_q, EV_EXIT, 0); 220 rb->queue_post(&thread_q, EV_EXIT, 0);
221 rb->thread_wait(thread_id); 221 rb->thread_wait(thread_id);
@@ -236,174 +236,119 @@ bool exit_tsr(bool reenter)
236unsigned long thread_stack[THREAD_STACK_SIZE/sizeof(long)]; 236unsigned long thread_stack[THREAD_STACK_SIZE/sizeof(long)];
237 237
238#if CONFIG_CHARGING || defined(HAVE_USB_POWER) 238#if CONFIG_CHARGING || defined(HAVE_USB_POWER)
239unsigned int charge_state(void) 239static unsigned int charge_state(void)
240{ 240{
241 unsigned int ret = 0; 241 unsigned int ret = 0;
242#if CONFIG_CHARGING 242#if CONFIG_CHARGING
243 if(rb->charger_inserted()) 243 if (rb->charger_inserted())
244 ret = BIT_CHARGER; 244 ret = BIT_CHARGER;
245#if CONFIG_CHARGING == CHARGING_MONITOR 245#if CONFIG_CHARGING == CHARGING_MONITOR
246 if(rb->charging_state()) 246 if (rb->charging_state())
247 ret |= BIT_CHARGING; 247 ret |= BIT_CHARGING;
248#endif 248#endif
249#endif 249#endif
250#ifdef HAVE_USB_POWER 250#ifdef HAVE_USB_POWER
251 if(rb->usb_powered()) 251 if (rb->usb_powered())
252 ret |= BIT_USB_POWER; 252 ret |= BIT_USB_POWER;
253#endif 253#endif
254 return ret; 254 return ret;
255} 255}
256#endif 256#endif
257 257
258void thread(void) 258
259static bool flush_buffer(void)
259{ 260{
260 bool got_info = false, timeflag = false, in_usb_mode = false; 261 int fd, secs;
261 int fd, buffelements, tick = 1, i = 0, skipped = 0, exit = 0; 262 unsigned int i;
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;
266#endif
267 long sleep_time = 5 * HZ;
268
269 struct queue_event ev;
270 263
271 buffelements = sizeof(bat)/sizeof(struct batt_info); 264 /* don't access the disk when in usb mode, or when no data is available */
265 if (in_usb_mode || (buf_idx == 0))
266 {
267 return false;
268 }
272 269
273#ifndef HAVE_FLASH_STORAGE 270 fd = rb->open(BATTERY_LOG, O_RDWR | O_CREAT | O_APPEND);
274 if(rb->global_settings->disk_spindown > 1) 271 if (fd < 0)
275 sleep_time = (rb->global_settings->disk_spindown - 1) * HZ; 272 {
276#endif 273 return false;
274 }
277 275
278 do 276 for (i = 0; i < buf_idx; i++)
279 { 277 {
280 if(!in_usb_mode && got_info && 278 secs = bat[i].ticks/HZ;
281 (exit || timeflag || rb->ata_disk_is_active()) ) 279 rb->fdprintf(fd,
282 { 280 "%02d:%02d:%02d, %05d, %03d%%, "
283 int last, secs, j, temp = skipped; 281 "%02d:%02d, %04d, "
284
285 fd = rb->open(BATTERY_LOG, O_RDWR | O_CREAT | O_APPEND);
286 if(fd < 0)
287 exit = 1;
288 else
289 {
290 do
291 {
292 if(skipped)
293 {
294 last = buffelements;
295 fst /= HZ;
296 lst /= HZ;
297 rb->fdprintf(fd,"-Skipped %d measurements from "
298 "%02d:%02d:%02d to %02d:%02d:%02d-\n",skipped,
299 HMS(fst),HMS(lst));
300 skipped = 0;
301 }
302 else
303 {
304 last = i;
305 i = 0;
306 }
307
308 for(j = i; j < last; j++)
309 {
310 secs = bat[j].ticks/HZ;
311 rb->fdprintf(fd,
312 "%02d:%02d:%02d, %05d, %03d%%, "
313 "%02d:%02d, %04d, %04d"
314#if CONFIG_CHARGING 282#if CONFIG_CHARGING
315 ", %c" 283 " %c"
316#if CONFIG_CHARGING == CHARGING_MONITOR 284#if CONFIG_CHARGING == CHARGING_MONITOR
317 ", %c" 285 ", %c"
318#endif 286#endif
319#endif 287#endif
320#ifdef HAVE_USB_POWER 288#ifdef HAVE_USB_POWER
321 ", %c" 289 ", %c"
322#endif 290#endif
323 "\n", 291 "\n",
324 292
325 HMS(secs), secs, bat[j].level, 293 HMS(secs), secs, bat[i].level,
326 bat[j].eta / 60, bat[j].eta % 60, 294 bat[i].eta / 60, bat[i].eta % 60,
327 bat[j].voltage, 295 bat[i].voltage
328 temp + 1 + (j-i)
329#if CONFIG_CHARGING 296#if CONFIG_CHARGING
330 ,(bat[j].flags & BIT_CHARGER)?'A':'-' 297 , (bat[i].flags & BIT_CHARGER) ? 'A' : '-'
331#if CONFIG_CHARGING == CHARGING_MONITOR 298#if CONFIG_CHARGING == CHARGING_MONITOR
332 ,(bat[j].flags & BIT_CHARGING)?'C':'-' 299 , (bat[i].flags & BIT_CHARGING) ? 'C' : '-'
333#endif 300#endif
334#endif 301#endif
335#ifdef HAVE_USB_POWER 302#ifdef HAVE_USB_POWER
336 ,(bat[j].flags & BIT_USB_POWER)?'U':'-' 303 , (bat[i].flags & BIT_USB_POWER) ? 'U' : '-'
337#endif 304#endif
338 305 );
339 ); 306 }
340 if(!j % 100 && !j) /* yield() at every 100 writes */ 307 rb->close(fd);
341 rb->yield(); 308
342 } 309 buf_idx = 0;
343 temp += j - i; 310 return true;
344 311}
345 }while(i != 0); 312
346 313
347 rb->close(fd); 314void thread(void)
348 tick = *rb->current_tick; 315{
349 got_info = false; 316 bool exit = false;
350 timeflag = false; 317 char *exit_reason = "unknown";
351 } 318 long sleep_time = 60 * HZ;
352 } 319 struct queue_event ev;
353 else 320 int fd;
354 { 321
355 unsigned int current_voltage; 322 in_usb_mode = false;
356 if( 323 buf_idx = 0;
357#if CONFIG_CODEC == SWCODEC 324
358 !rb->pcm_is_playing() 325 while (!exit)
359#else 326 {
360 !rb->mp3_is_playing() 327 /* add data to buffer */
361#endif 328 if (buf_idx < BUF_ELEMENTS)
362 && (*rb->current_tick - tick) > DISK_SPINDOWN_TIMEOUT * HZ) 329 {
363 timeflag = true; 330 bat[buf_idx].ticks = *rb->current_tick;
364 331 bat[buf_idx].level = rb->battery_level();
365 if(last_voltage != (current_voltage=rb->battery_voltage()) 332 bat[buf_idx].eta = rb->battery_time();
333 bat[buf_idx].voltage = rb->battery_voltage();
366#if CONFIG_CHARGING || defined(HAVE_USB_POWER) 334#if CONFIG_CHARGING || defined(HAVE_USB_POWER)
367 || last_state != charge_state() 335 bat[buf_idx].flags = charge_state();
368#endif 336#endif
369 ) 337 buf_idx++;
370 { 338 rb->register_ata_idle_func(flush_buffer);
371 if(i == buffelements) 339 }
372 {
373 if(!skipped++)
374 fst = bat[0].ticks;
375 i = 0;
376 }
377 else if(skipped)
378 {
379 skipped++;
380 lst = bat[i].ticks;
381 }
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();
388#endif
389 i++;
390 got_info = true;
391 }
392
393 }
394 340
395 if(exit) 341 /* What to do when the measurement buffer is full:
396 { 342 1) save our measurements to disk but waste some power doing so?
397 if(exit == 2) 343 2) throw away measurements to save some power?
398 rb->splash(HZ, 344 The choice made here is to save the measurements. It is quite unusual
399#ifdef HAVE_LCD_BITMAP 345 for this to occur because it requires > 16 hours of no disk activity.
400 "Exiting battery_bench..."); 346 */
401#else 347 if (buf_idx == BUF_ELEMENTS) {
402 "bench exit"); 348 flush_buffer();
403#endif
404 return;
405 } 349 }
406 350
351 /* sleep some time until next measurement */
407 rb->queue_wait_w_tmo(&thread_q, &ev, sleep_time); 352 rb->queue_wait_w_tmo(&thread_q, &ev, sleep_time);
408 switch (ev.id) 353 switch (ev.id)
409 { 354 {
@@ -416,20 +361,38 @@ void thread(void)
416 rb->usb_acknowledge(SYS_USB_DISCONNECTED_ACK); 361 rb->usb_acknowledge(SYS_USB_DISCONNECTED_ACK);
417 break; 362 break;
418 case SYS_POWEROFF: 363 case SYS_POWEROFF:
419 exit = 1; 364 exit_reason = "power off";
365 exit = true;
420 break; 366 break;
421 case EV_EXIT: 367 case EV_EXIT:
422 exit = 2; 368#ifdef HAVE_LCD_BITMAP
369 rb->splash(HZ, "Exiting battery_bench...");
370#else
371 rb->splash(HZ, "bench exit");
372#endif
373 exit_reason = "plugin exit";
374 exit = true;
423 break; 375 break;
424 } 376 }
425 } while (1); 377 }
378
379 /* unregister flush callback and flush to disk */
380 rb->unregister_ata_idle_func(flush_buffer, true);
381
382 /* log end of bench and exit reason */
383 fd = rb->open(BATTERY_LOG, O_RDWR | O_CREAT | O_APPEND);
384 if (fd >= 0)
385 {
386 rb->fdprintf(fd, "--Battery bench ended, reason: %s--\n", exit_reason);
387 rb->close(fd);
388 }
426} 389}
427 390
428 391
429#ifdef HAVE_LCD_BITMAP 392#ifdef HAVE_LCD_BITMAP
430typedef void (*plcdfunc)(int x, int y, const unsigned char *str); 393typedef void (*plcdfunc)(int x, int y, const unsigned char *str);
431 394
432void put_centered_str(const char* str, plcdfunc putsxy, int lcd_width, int line) 395static void put_centered_str(const char* str, plcdfunc putsxy, int lcd_width, int line)
433{ 396{
434 int strwdt, strhgt; 397 int strwdt, strhgt;
435 rb->lcd_getstringsize(str, &strwdt, &strhgt); 398 rb->lcd_getstringsize(str, &strwdt, &strhgt);
@@ -452,7 +415,7 @@ int main(void)
452 rb->lcd_clear_display(); 415 rb->lcd_clear_display();
453 rb->lcd_setfont(FONT_SYSFIXED); 416 rb->lcd_setfont(FONT_SYSFIXED);
454 417
455 for(i = 0; i<(int)(sizeof(msgs)/sizeof(char *)); i++) 418 for (i = 0; i<(int)(sizeof(msgs)/sizeof(char *)); i++)
456 put_centered_str(msgs[i],rb->lcd_putsxy,LCD_WIDTH,i+1); 419 put_centered_str(msgs[i],rb->lcd_putsxy,LCD_WIDTH,i+1);
457#else 420#else
458 rb->lcd_puts_scroll(0, 0, "Batt.Bench."); 421 rb->lcd_puts_scroll(0, 0, "Batt.Bench.");
@@ -473,7 +436,7 @@ int main(void)
473 do 436 do
474 { 437 {
475 button = rb->button_get(true); 438 button = rb->button_get(true);
476 switch(button) 439 switch (button)
477 { 440 {
478 case BATTERY_ON: 441 case BATTERY_ON:
479#ifdef BATTERY_RC_ON 442#ifdef BATTERY_RC_ON
@@ -484,23 +447,24 @@ int main(void)
484 case BATTERY_OFF: 447 case BATTERY_OFF:
485#ifdef BATTERY_RC_OFF 448#ifdef BATTERY_RC_OFF
486 case BATTERY_RC_OFF: 449 case BATTERY_RC_OFF:
487#endif 450#endif
488 return PLUGIN_OK; 451 return PLUGIN_OK;
489 452
490 default: if(rb->default_event_handler(button) == SYS_USB_CONNECTED) 453 default:
454 if (rb->default_event_handler(button) == SYS_USB_CONNECTED)
491 return PLUGIN_USB_CONNECTED; 455 return PLUGIN_USB_CONNECTED;
492 } 456 }
493 }while(!on); 457 }while(!on);
494 458
495 fd = rb->open(BATTERY_LOG, O_RDONLY); 459 fd = rb->open(BATTERY_LOG, O_RDONLY);
496 if(fd < 0) 460 if (fd < 0)
497 { 461 {
498 fd = rb->open(BATTERY_LOG, O_RDWR | O_CREAT); 462 fd = rb->open(BATTERY_LOG, O_RDWR | O_CREAT);
499 if(fd >= 0) 463 if (fd >= 0)
500 { 464 {
501 rb->fdprintf(fd, 465 rb->fdprintf(fd,
502 "This plugin will log your battery performance in a\n" 466 "This plugin will log your battery performance in a\n"
503 "file (%s) every time the disk is accessed (or every hour).\n" 467 "file (%s) every minute.\n"
504 "To properly test your battery:\n" 468 "To properly test your battery:\n"
505 "1) Select and playback an album. " 469 "1) Select and playback an album. "
506 "(Be sure to be more than the player's buffer)\n" 470 "(Be sure to be more than the player's buffer)\n"
@@ -512,13 +476,10 @@ int main(void)
512 "Do not enter another plugin during the test or else the " 476 "Do not enter another plugin during the test or else the "
513 "logging activity will end.\n\n" 477 "logging activity will end.\n\n"
514 "P.S: You can decide how you will make your tests.\n" 478 "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 " 479 "Just don't open another plugin to be sure that your log "
516 "will continue.\n" 480 "will continue.\n\n"
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" 481 "Battery type: %d mAh Buffer Entries: %d\n"
520 " Time:, Seconds:, Level:, Time Left:, Voltage[mV]:," 482 " Time:, Seconds:, Level:, Time Left:, Voltage[mV]:"
521 " M/DA:"
522#if CONFIG_CHARGING 483#if CONFIG_CHARGING
523 ", C:" 484 ", C:"
524#endif 485#endif
@@ -530,7 +491,7 @@ int main(void)
530#endif 491#endif
531 "\n" 492 "\n"
532 ,BATTERY_LOG,rb->global_settings->battery_capacity, 493 ,BATTERY_LOG,rb->global_settings->battery_capacity,
533 BUF_SIZE / (unsigned)sizeof(struct batt_info)); 494 (int)BUF_ELEMENTS);
534 rb->close(fd); 495 rb->close(fd);
535 } 496 }
536 else 497 else
@@ -548,10 +509,10 @@ int main(void)
548 } 509 }
549 510
550 rb->queue_init(&thread_q, true); /* put the thread's queue in the bcast list */ 511 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, 512 if ((thread_id = rb->create_thread(thread, thread_stack,
552 sizeof(thread_stack), 0, "Battery Benchmark" 513 sizeof(thread_stack), 0, "Battery Benchmark"
553 IF_PRIO(, PRIORITY_BACKGROUND) 514 IF_PRIO(, PRIORITY_BACKGROUND)
554 IF_COP(, CPU))) == NULL) 515 IF_COP(, CPU))) == NULL)
555 { 516 {
556 rb->splash(HZ, "Cannot create thread!"); 517 rb->splash(HZ, "Cannot create thread!");
557 return PLUGIN_ERROR; 518 return PLUGIN_ERROR;
@@ -562,4 +523,4 @@ int main(void)
562 return PLUGIN_OK; 523 return PLUGIN_OK;
563} 524}
564 525
565#endif 526#endif /* SIMULATOR */