Index: apps/plugins/battery_bench.c =================================================================== --- apps/plugins/battery_bench.c (revision 17943) +++ apps/plugins/battery_bench.c (working copy) @@ -26,11 +26,10 @@ #define BATTERY_LOG "/battery_bench.txt" #define BUF_SIZE 16000 -#define DISK_SPINDOWN_TIMEOUT 3600 #define EV_EXIT 1337 -/* seems to work with 1300, but who knows... */ +/* seems to work with 1300, but who knows... */ #define THREAD_STACK_SIZE DEFAULT_STACK_SIZE + 0x200 #if CONFIG_KEYPAD == RECORDER_PAD @@ -62,7 +61,7 @@ #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \ (CONFIG_KEYPAD == IRIVER_H300_PAD) - + #define BATTERY_ON BUTTON_ON #define BATTERY_RC_ON BUTTON_RC_ON @@ -182,7 +181,7 @@ { (void)parameter; rb = api; - + return main(); } @@ -198,9 +197,13 @@ unsigned short flags; } bat[BUF_SIZE/sizeof(struct batt_info)]; -struct thread_entry *thread_id; -struct event_queue thread_q; +#define BUF_ELEMENTS (sizeof(bat)/sizeof(struct batt_info)) +static struct thread_entry *thread_id; +static struct event_queue thread_q; +static bool in_usb_mode; +static unsigned int buf_idx; + bool exit_tsr(bool reenter) { bool exit = true; @@ -230,184 +233,125 @@ #define BIT_CHARGING 0x2 #define BIT_USB_POWER 0x4 -#define HMS(x) (x)/3600,((x)%3600)/60,((x)%3600)%60 +#define HMS(x) (x)/3600,((x)%3600)/60,((x)%3600)%60 /* use long for aligning */ unsigned long thread_stack[THREAD_STACK_SIZE/sizeof(long)]; #if CONFIG_CHARGING || defined(HAVE_USB_POWER) -unsigned int charge_state(void) +static unsigned int charge_state(void) { unsigned int ret = 0; #if CONFIG_CHARGING - if(rb->charger_inserted()) + if (rb->charger_inserted()) ret = BIT_CHARGER; #if CONFIG_CHARGING == CHARGING_MONITOR - if(rb->charging_state()) + if (rb->charging_state()) ret |= BIT_CHARGING; #endif #endif #ifdef HAVE_USB_POWER - if(rb->usb_powered()) + if (rb->usb_powered()) ret |= BIT_USB_POWER; #endif - return ret; + return ret; } #endif -void thread(void) + +static bool flush_buffer(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; -#if CONFIG_CHARGING || defined(HAVE_USB_POWER) - unsigned int last_state = 0; -#endif - long sleep_time = 5 * HZ; - - struct queue_event ev; + int fd, secs; + unsigned int i; - buffelements = sizeof(bat)/sizeof(struct batt_info); + /* don't access the disk when in usb mode, or when no data is available */ + if (in_usb_mode || (buf_idx == 0)) + { + return false; + } -#ifndef HAVE_FLASH_STORAGE - if(rb->global_settings->disk_spindown > 1) - sleep_time = (rb->global_settings->disk_spindown - 1) * HZ; -#endif - - do + fd = rb->open(BATTERY_LOG, O_RDWR | O_CREAT | O_APPEND); + if (fd < 0) { - 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; - } + return false; + } - for(j = i; j < last; j++) - { - secs = bat[j].ticks/HZ; - rb->fdprintf(fd, - "%02d:%02d:%02d, %05d, %03d%%, " - "%02d:%02d, %04d, %04d" + for (i = 0; i < buf_idx; i++) + { + secs = bat[i].ticks/HZ; + rb->fdprintf(fd, + "%02d:%02d:%02d, %05d, %03d%%, " + "%02d:%02d, %04d, " #if CONFIG_CHARGING - ", %c" + " %c" #if CONFIG_CHARGING == CHARGING_MONITOR - ", %c" + ", %c" #endif #endif #ifdef HAVE_USB_POWER - ", %c" + ", %c" #endif - "\n", - - HMS(secs), secs, bat[j].level, - bat[j].eta / 60, bat[j].eta % 60, - bat[j].voltage, - temp + 1 + (j-i) + "\n", + + HMS(secs), secs, bat[i].level, + bat[i].eta / 60, bat[i].eta % 60, + bat[i].voltage #if CONFIG_CHARGING - ,(bat[j].flags & BIT_CHARGER)?'A':'-' + , (bat[i].flags & BIT_CHARGER) ? 'A' : '-' #if CONFIG_CHARGING == CHARGING_MONITOR - ,(bat[j].flags & BIT_CHARGING)?'C':'-' + , (bat[i].flags & BIT_CHARGING) ? 'C' : '-' #endif #endif #ifdef HAVE_USB_POWER - ,(bat[j].flags & BIT_USB_POWER)?'U':'-' + , (bat[i].flags & BIT_USB_POWER) ? 'U' : '-' #endif - - ); - 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 - { - unsigned int current_voltage; - if( -#if CONFIG_CODEC == SWCODEC - !rb->pcm_is_playing() -#else - !rb->mp3_is_playing() -#endif - && (*rb->current_tick - tick) > DISK_SPINDOWN_TIMEOUT * HZ) - timeflag = true; - - if(last_voltage != (current_voltage=rb->battery_voltage()) + ); + } + rb->close(fd); + + buf_idx = 0; + return true; +} + + +void thread(void) +{ + int exit = 0; + long sleep_time = 60 * HZ; + struct queue_event ev; + + in_usb_mode = false; + buf_idx = 0; + + while (!exit) + { + /* add data to buffer */ + if (buf_idx < BUF_ELEMENTS) + { + bat[buf_idx].ticks = *rb->current_tick; + bat[buf_idx].level = rb->battery_level(); + bat[buf_idx].eta = rb->battery_time(); + bat[buf_idx].voltage = rb->battery_voltage(); #if CONFIG_CHARGING || defined(HAVE_USB_POWER) - || last_state != charge_state() + bat[buf_idx].flags = charge_state(); #endif - ) - { - 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 = current_voltage; -#if CONFIG_CHARGING || defined(HAVE_USB_POWER) - bat[i].flags = last_state = charge_state(); -#endif - i++; - got_info = true; - } - - } - - if(exit) + buf_idx++; + rb->register_ata_idle_func(flush_buffer); + } + else { - if(exit == 2) - rb->splash(HZ, -#ifdef HAVE_LCD_BITMAP - "Exiting battery_bench..."); -#else - "bench exit"); -#endif - return; + /* Buffer is full, so we've arrived at a dilemma, do we: + 1) save our measurements to disk but waste some power doing so? + 2) throw away measurements? + */ + flush_buffer(); } - + + /* sleep some time until next measurement */ rb->queue_wait_w_tmo(&thread_q, &ev, sleep_time); switch (ev.id) { - case SYS_USB_CONNECTED: + case SYS_USB_CONNECTED: in_usb_mode = true; rb->usb_acknowledge(SYS_USB_CONNECTED_ACK); break; @@ -422,14 +366,25 @@ exit = 2; break; } - } while (1); + + /* show splash on normal exit */ + if (exit == 2) +#ifdef HAVE_LCD_BITMAP + rb->splash(HZ, "Exiting battery_bench..."); +#else + rb->splash(HZ, "bench exit"); +#endif + } + + /* unregister flush callback and flush to disk */ + rb->unregister_ata_idle_func(flush_buffer, true); } #ifdef HAVE_LCD_BITMAP typedef void (*plcdfunc)(int x, int y, const unsigned char *str); -void put_centered_str(const char* str, plcdfunc putsxy, int lcd_width, int line) +static void put_centered_str(const char* str, plcdfunc putsxy, int lcd_width, int line) { int strwdt, strhgt; rb->lcd_getstringsize(str, &strwdt, &strhgt); @@ -445,21 +400,21 @@ int i; const char *msgs[] = { "Battery Benchmark","Check file", BATTERY_LOG, "for more info", BATTERY_ON_TXT, BATTERY_OFF_TXT }; -#endif +#endif rb->lcd_clear_display(); #ifdef HAVE_LCD_BITMAP rb->lcd_clear_display(); rb->lcd_setfont(FONT_SYSFIXED); - for(i = 0; i<(int)(sizeof(msgs)/sizeof(char *)); i++) + for (i = 0; i<(int)(sizeof(msgs)/sizeof(char *)); i++) put_centered_str(msgs[i],rb->lcd_putsxy,LCD_WIDTH,i+1); #else rb->lcd_puts_scroll(0, 0, "Batt.Bench."); rb->lcd_puts_scroll(0, 1, "PLAY/STOP"); #endif rb->lcd_update(); - + #ifdef HAVE_REMOTE_LCD rb->lcd_remote_clear_display(); put_centered_str(msgs[0],rb->lcd_remote_putsxy,LCD_REMOTE_WIDTH,0); @@ -469,38 +424,39 @@ rb->lcd_remote_putsxy,LCD_REMOTE_WIDTH,2); rb->lcd_remote_update(); #endif - + do { button = rb->button_get(true); - switch(button) + switch (button) { case BATTERY_ON: #ifdef BATTERY_RC_ON case BATTERY_RC_ON: -#endif +#endif on = true; - break; - case BATTERY_OFF: + break; + case BATTERY_OFF: #ifdef BATTERY_RC_OFF case BATTERY_RC_OFF: -#endif +#endif return PLUGIN_OK; - - default: if(rb->default_event_handler(button) == SYS_USB_CONNECTED) + + default: + if (rb->default_event_handler(button) == SYS_USB_CONNECTED) return PLUGIN_USB_CONNECTED; } }while(!on); - + fd = rb->open(BATTERY_LOG, O_RDONLY); - if(fd < 0) + if (fd < 0) { fd = rb->open(BATTERY_LOG, O_RDWR | O_CREAT); - if(fd >= 0) + 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" + "file (%s) every minute.\n" "To properly test your battery:\n" "1) Select and playback an album. " "(Be sure to be more than the player's buffer)\n" @@ -512,13 +468,10 @@ "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" + "Just don't open another plugin to be sure that your log " + "will continue.\n\n" "Battery type: %d mAh Buffer Entries: %d\n" - " Time:, Seconds:, Level:, Time Left:, Voltage[mV]:," - " M/DA:" + " Time:, Seconds:, Level:, Time Left:, Voltage[mV]:" #if CONFIG_CHARGING ", C:" #endif @@ -530,7 +483,7 @@ #endif "\n" ,BATTERY_LOG,rb->global_settings->battery_capacity, - BUF_SIZE / (unsigned)sizeof(struct batt_info)); + (int)BUF_ELEMENTS); rb->close(fd); } else @@ -546,20 +499,20 @@ rb->fdprintf(fd, "\n--File already present. Resuming Benchmark--\n"); rb->close(fd); } - + rb->queue_init(&thread_q, true); /* put the thread's queue in the bcast list */ - if((thread_id = rb->create_thread(thread, thread_stack, - sizeof(thread_stack), 0, "Battery Benchmark" + if ((thread_id = rb->create_thread(thread, thread_stack, + sizeof(thread_stack), 0, "Battery Benchmark" IF_PRIO(, PRIORITY_BACKGROUND) - IF_COP(, CPU))) == NULL) + IF_COP(, CPU))) == NULL) { rb->splash(HZ, "Cannot create thread!"); return PLUGIN_ERROR; } - + rb->plugin_tsr(exit_tsr); - + return PLUGIN_OK; } -#endif +#endif /* SIMULATOR */ Index: apps/plugin.c =================================================================== --- apps/plugin.c (revision 17943) +++ apps/plugin.c (working copy) @@ -206,7 +206,7 @@ lcd_remote_bitmap, #endif viewport_set_defaults, - + /* list */ gui_synclist_init, gui_synclist_set_nb_items, @@ -238,7 +238,7 @@ #ifdef HAVE_TOUCHPAD touchpad_set_mode, #endif - + #ifdef HAVE_BUTTON_LIGHT buttonlight_set_timeout, buttonlight_off, @@ -263,9 +263,10 @@ read_line, settings_parseline, ata_sleep, - ata_disk_is_active, ata_spin, ata_spindown, + register_ata_idle_func, + unregister_ata_idle_func, reload_directory, create_numbered_filename, file_exists, @@ -701,8 +702,8 @@ #endif plugin_loaded = true; - + #if defined HAVE_LCD_BITMAP && LCD_DEPTH > 1 old_backdrop = lcd_get_backdrop(); #endif Index: apps/plugin.h =================================================================== --- apps/plugin.h (revision 17943) +++ apps/plugin.h (working copy) @@ -87,6 +87,7 @@ #include "buffering.h" #include "tagcache.h" #include "viewport.h" +#include "ata_idle_notify.h" #ifdef HAVE_ALBUMART #include "albumart.h" @@ -126,12 +127,12 @@ #define PLUGIN_MAGIC 0x526F634B /* RocK */ /* increase this every time the api struct changes */ -#define PLUGIN_API_VERSION 118 +#define PLUGIN_API_VERSION 119 /* update this to latest version if a change to the api struct breaks backwards compatibility (and please take the opportunity to sort in any new function which are "waiting" at the end of the function table) */ -#define PLUGIN_MIN_API_VERSION 117 +#define PLUGIN_MIN_API_VERSION 118 /* plugin return codes */ enum plugin_status { @@ -220,7 +221,7 @@ #ifdef HAVE_LCD_INVERT void (*lcd_set_invert_display)(bool yesno); #endif /* HAVE_LCD_INVERT */ - + #ifdef HAVE_LCD_ENABLE void (*lcd_set_enable_hook)(void (*enable_hook)(void)); struct event_queue *button_queue; @@ -333,7 +334,7 @@ intptr_t (*button_get_data)(void); #endif void (*button_clear_queue)(void); - int (*button_queue_count)(void); + int (*button_queue_count)(void); #ifdef HAS_BUTTON_HOLD bool (*button_hold)(void); #endif @@ -364,16 +365,16 @@ int (*read_line)(int fd, char* buffer, int buffer_size); bool (*settings_parseline)(char* line, char** name, char** value); void (*ata_sleep)(void); - bool (*ata_disk_is_active)(void); void (*ata_spin)(void); void (*ata_spindown)(int seconds); + void (*register_ata_idle_func)(ata_idle_notify function); + void (*unregister_ata_idle_func)(ata_idle_notify function, bool run); void (*reload_directory)(void); char *(*create_numbered_filename)(char *buffer, const char *path, const char *prefix, const char *suffix, int numberlen IF_CNFN_NUM_(, int *num)); bool (*file_exists)(const char *file); - /* dir */ DIR* (*opendir)(const char* name); int (*closedir)(DIR* dir); @@ -393,7 +394,7 @@ size_t stack_size, unsigned flags, const char *name IF_PRIO(, int priority) - IF_COP(, unsigned int core)); + IF_COP(, unsigned int core)); void (*thread_exit)(void); void (*thread_wait)(struct thread_entry *thread); #if CONFIG_CODEC == SWCODEC @@ -595,7 +596,7 @@ /* scroll bar */ struct gui_syncstatusbar *statusbars; void (*gui_syncstatusbar_draw)(struct gui_syncstatusbar * bars, bool force_redraw); - + /* options */ const struct settings_list* (*find_setting)(const void* variable, int *id); bool (*option_screen)(const struct settings_list *setting, @@ -609,8 +610,8 @@ const char* no_str, int no_voice, void (*function)(bool)); bool (*set_int)(const unsigned char* string, const char* unit, int voice_unit, - const int* variable, void (*function)(int), int step, - int min, int max, + const int* variable, void (*function)(int), int step, + int min, int max, void (*formatter)(char*, size_t, int, const char*) ); bool (*set_bool)(const char* string, const bool* variable ); Index: firmware/events.c =================================================================== --- firmware/events.c (revision 17943) +++ firmware/events.c (working copy) @@ -36,14 +36,14 @@ bool add_event(unsigned short id, bool oneshot, void (*handler)) { int i; - + /* Check if the event already exists. */ for (i = 0; i < MAX_SYS_EVENTS; i++) { if (events[i].callback == handler && events[i].id == id) return false; } - + /* Try to find a free slot. */ for (i = 0; i < MAX_SYS_EVENTS; i++) { @@ -55,7 +55,7 @@ return true; } } - + panicf("event line full"); return false; } @@ -63,7 +63,7 @@ void remove_event(unsigned short id, void (*handler)) { int i; - + for (i = 0; i < MAX_SYS_EVENTS; i++) { if (events[i].id == id && events[i].callback == handler) @@ -72,20 +72,18 @@ return; } } - - panicf("event %d not found", (int)id); } void send_event(unsigned short id, void *data) { int i; - + for (i = 0; i < MAX_SYS_EVENTS; i++) { if (events[i].id == id && events[i].callback != NULL) { events[i].callback(data); - + if (events[i].oneshot) events[i].callback = NULL; }