From 00598459bbd415f68bef86f79c796b9da608d905 Mon Sep 17 00:00:00 2001 From: Hristo Kovachev Date: Wed, 25 Jan 2006 18:35:36 +0000 Subject: And the plugin itself ... :) git-svn-id: svn://svn.rockbox.org/rockbox/trunk@8452 a1c6a512-1295-4272-9138-f99709370657 --- apps/plugins/battery_bench.c | 339 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 339 insertions(+) create mode 100644 apps/plugins/battery_bench.c diff --git a/apps/plugins/battery_bench.c b/apps/plugins/battery_bench.c new file mode 100644 index 0000000000..3eebb44d8f --- /dev/null +++ b/apps/plugins/battery_bench.c @@ -0,0 +1,339 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * + * Copyright (C) 2006 Alexander Spyridakis, Hristo Kovachev + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#ifndef SIMULATOR /* not for the simulator */ + +#include "plugin.h" +PLUGIN_HEADER + +#define BATTERY_LOG "/battery_bench.txt" +#define BUF_SIZE 16000 +#define DISK_SPINDOWN_TIMEOUT 3600 + +#define EV_EXIT 1337 + +#if CONFIG_KEYPAD == RECORDER_PAD +#define BATTERY_ON BUTTON_ON +#define BATTERY_OFF BUTTON_OFF + +#elif CONFIG_KEYPAD == ONDIO_PAD +#define BATTERY_ON BUTTON_RIGHT +#define BATTERY_OFF BUTTON_OFF + +#elif CONFIG_KEYPAD == PLAYER_PAD +#define BATTERY_ON BUTTON_ON +#define BATTERY_OFF BUTTON_STOP + +#elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \ + (CONFIG_KEYPAD == IRIVER_H300_PAD) + +#define BATTERY_ON BUTTON_ON +#define BATTERY_RC_ON BUTTON_RC_ON + +#define BATTERY_OFF BUTTON_OFF +#define BATTERY_RC_OFF BUTTON_RC_STOP +#endif + + +/***************** Plugin Entry Point *****************/ +static struct plugin_api* rb; +int main(void); +void exit_tsr(void); +void thread(void); + +enum plugin_status plugin_start(struct plugin_api* api, void* parameter) +{ + (void)parameter; + rb = api; + + return main(); +} + +struct +{ + int id; + bool ended; +} s_thread; + +/* Struct for battery information */ +struct batt_info +{ + int ticks, level, eta; + unsigned int voltage; +}; + +struct event_queue thread_q; + +void exit_tsr(void) +{ + rb->queue_post(&thread_q, EV_EXIT, NULL); + while (!s_thread.ended) + rb->yield(); + /* remove the thread's queue from the broadcast list */ + rb->queue_delete(&thread_q); +} + +#define HMS(x) (x)/3600,((x)%3600)/60,((x)%3600)%60 +void thread(void) +{ + bool got_info = false, timeflag = false, in_usb_mode = false; + int fd, buffelements, tick = 1, i = 0, skipped = 0, exit = 0; + int fst = 0, lst = 0; /* first and last skipped tick */ + unsigned int last_voltage = 0; + long sleep_time; + + struct event ev; + + struct batt_info bat[buffelements = (BUF_SIZE / sizeof(struct batt_info))]; + + sleep_time = (rb->global_settings->disk_spindown > 1) ? + (rb->global_settings->disk_spindown - 1) * HZ : 5 * HZ; + + do + { + if(!in_usb_mode && got_info && + (exit || timeflag || rb->ata_disk_is_active()) ) + { + int last, secs, j, temp = skipped; + + fd = rb->open(BATTERY_LOG, O_RDWR | O_CREAT | O_APPEND); + if(fd < 0) + exit = 1; + else + { + do + { + if(skipped) + { + last = buffelements; + fst /= HZ; + lst /= HZ; + rb->fdprintf(fd,"-Skipped %d measurements from " + "%02d:%02d:%02d to %02d:%02d:%02d-\n",skipped, + HMS(fst),HMS(lst)); + skipped = 0; + } + else + { + last = i; + i = 0; + } + + for(j = i; j < last; j++) + { + secs = bat[j].ticks/HZ; + rb->fdprintf(fd, + "%02d:%02d:%02d, %05d, %03d%%, " + "%02d:%02d, %04d, %04d\n", + HMS(secs), secs, bat[j].level, + bat[j].eta / 60, bat[j].eta % 60, + bat[j].voltage * 10, temp + 1 + (j-i)); + if(!j % 100 && !j) /* yield() at every 100 writes */ + rb->yield(); + } + temp += j - i; + + }while(i != 0); + + rb->close(fd); + tick = *rb->current_tick; + got_info = false; + timeflag = false; + } + } + else + { + if(!rb->pcm_is_playing() && + (*rb->current_tick - tick) > DISK_SPINDOWN_TIMEOUT * HZ) + timeflag = true; + + if(last_voltage != rb->battery_voltage()) + { + if(i == buffelements) + { + if(!skipped++) + fst = bat[0].ticks; + i = 0; + } + else if(skipped) + { + skipped++; + lst = bat[i].ticks; + } + bat[i].ticks = *rb->current_tick; + bat[i].level = rb->battery_level(); + bat[i].eta = rb->battery_time(); + last_voltage = bat[i++].voltage = rb->battery_voltage(); + got_info = true; + } + + } + + if(exit) + { + if(exit == 2) + rb->splash(HZ,true,"Exiting battery_bench..."); + s_thread.ended = true; + rb->remove_thread(s_thread.id); + rb->yield(); /* exit the thread, this yield() won't return */ + } + + rb->queue_wait_w_tmo(&thread_q, &ev, sleep_time); + switch (ev.id) + { + case SYS_USB_CONNECTED: + in_usb_mode = true; + rb->usb_acknowledge(SYS_USB_CONNECTED_ACK); + break; + case SYS_USB_DISCONNECTED: + in_usb_mode = false; + rb->usb_acknowledge(SYS_USB_DISCONNECTED_ACK); + break; + case SYS_POWEROFF: + exit = 1; + break; + case EV_EXIT: + exit = 2; + break; + } + } while (1); + +} + +int main(void) +{ + int stacksize, button, fd; + bool on = false; + void* stack; + + + rb->lcd_clear_display(); + +#ifdef HAVE_LCD_BITMAP + int strwdt, strhgt; + + rb->lcd_setfont(FONT_SYSFIXED); + + rb->lcd_getstringsize("Battery Benchmark", &strwdt, &strhgt); + rb->lcd_putsxy((LCD_WIDTH - strwdt)/2, strhgt, "Battery Benchmark"); + + rb->lcd_getstringsize("Check /battery_bench.txt", &strwdt, &strhgt); + rb->lcd_putsxy((LCD_WIDTH - strwdt)/2,strhgt * 3, + "Check /battery_bench.txt"); + rb->lcd_getstringsize("file for more info.", &strwdt, &strhgt); + rb->lcd_putsxy((LCD_WIDTH - strwdt)/2, strhgt * 4, "file for more info."); + rb->lcd_getstringsize("Play to start, OFF to quit", &strwdt, &strhgt); + rb->lcd_putsxy((LCD_WIDTH - strwdt)/2, strhgt * 5, + "PLAY to start, OFF to quit"); + + rb->lcd_update(); + +#else + rb->lcd_puts_scroll(0, 1, "Battery Benchmark"); + rb->lcd_puts_scroll(0, 2, "PLAY to start, OFF to quit"); +#endif + + do + { + button = rb->button_get(true); + switch(button) + { + case BATTERY_ON: +#ifdef BATTERY_RC_ON + case BATTERY_RC_ON: +#endif + on = true; + break; + case BATTERY_OFF: +#ifdef BATTERY_RC_OFF + case BATTERY_RC_OFF: +#endif + return PLUGIN_OK; + + default: if(rb->default_event_handler(button) == SYS_USB_CONNECTED) + return PLUGIN_USB_CONNECTED; + } + }while(!on); + + stack = rb->plugin_get_buffer(&stacksize); + /* long align it and leave some space (200bytes) for vars */ + stack = (void*)(((unsigned int)stack + 200) & ~3); + + stacksize = (stacksize - 200) & ~3; + if (stacksize < BUF_SIZE) + { + rb->splash(HZ*2, true, "Out of memory"); + return PLUGIN_ERROR; + } + + fd = rb->open(BATTERY_LOG, O_RDONLY); + if(fd < 0) + { + fd = rb->open(BATTERY_LOG, O_RDWR | O_CREAT); + if(fd >= 0) + { + rb->fdprintf(fd, + "This plugin will log your battery performance in a\n" + "file (%s) every time the disk is accessed (or every hour).\n" + "To properly test your battery:\n" + "1) Select and playback an album. " + "(Be sure to be more than the player's buffer)\n" + "2) Set to repeat.\n" + "3) Let the player run completely out of battery.\n" + "4) Recharge and copy (or whatever you want) the txt file to " + "your computer.\n" + "Now you can make graphs with the data of the battery log.\n" + "Do not enter another plugin during the test or else the " + "logging activity will end.\n\n" + "P.S: You can decide how you will make your tests.\n" + "Just don't open another plugin to be sure that your log " + "will continue.\n" + "M/DA (Measurements per Disk Activity) shows how many times\n" + "data was logged in the buffer between Disk Activity.\n\n" + "Battery type: %d mAh Buffer Entries: %d\n" + " Time:, Seconds:, Level:, Time Left:, Voltage[mV]:," + " M/DA:\n" + ,BATTERY_LOG,rb->global_settings->battery_capacity, + BUF_SIZE / sizeof(struct batt_info)); + rb->close(fd); + } + else + { + rb->splash(HZ / 2, true, "Cannot create file!"); + return PLUGIN_ERROR; + } + } + else + { + rb->close(fd); + fd = rb->open(BATTERY_LOG, O_RDWR | O_APPEND); + rb->fdprintf(fd, "\nFile already present. Resuming Benchmark\n"); + rb->close(fd); + } + + rb->queue_init(&thread_q); /* put the thread's queue in the bcast list */ + rb->memset(&s_thread, 0, sizeof(s_thread)); /* zero the struct */ + s_thread.id = rb->create_thread(thread, stack, + stacksize, "Battery Benchmark"); + rb->plugin_tsr(exit_tsr); + + return PLUGIN_OK; +} + +#endif -- cgit v1.2.3