From 20b0dd2788794521ac7f3eec1065b7de99e4a5aa Mon Sep 17 00:00:00 2001 From: Maurus Cuelenaere Date: Fri, 21 Aug 2009 22:54:23 +0000 Subject: A new implementation of logf, logfdisplay and logfdump. Flyspray: FS#10528 Author: Amaury Pouly git-svn-id: svn://svn.rockbox.org/rockbox/trunk@22462 a1c6a512-1295-4272-9138-f99709370657 --- apps/logfdisp.c | 293 ++++++++++++++++++++++++++------------------- firmware/common/sprintf.c | 5 + firmware/export/logf.h | 9 +- firmware/include/sprintf.h | 2 + firmware/logf.c | 212 ++++++++++++++++++++------------ 5 files changed, 318 insertions(+), 203 deletions(-) diff --git a/apps/logfdisp.c b/apps/logfdisp.c index da711bf1d3..41cb109efd 100644 --- a/apps/logfdisp.c +++ b/apps/logfdisp.c @@ -29,6 +29,7 @@ #include #include +#include #include "menu.h" #include "logf.h" #include "settings.h" @@ -36,90 +37,174 @@ #include "action.h" #ifdef HAVE_LCD_BITMAP -bool logfdisplay(void) +int compute_nb_lines(int w, struct font* font) { - int w, h; - int lines; - int columns; - int i; - int action; - - bool lcd = false; /* fixed atm */ - int index, user_index=0; + int i, nb_lines; + int cur_x, delta_x; + + if(logfindex == 0 && !logfwrap) + return 0; + + if(logfwrap) + i = logfindex; + else + i = 0; + + cur_x = 0; + nb_lines = 0; + + do { + if(logfbuffer[i] == '\0') + { + cur_x = 0; + nb_lines++; + } + else + { + /* does character fit on this line ? */ + delta_x = font_get_width(font, logfbuffer[i]); + + if(cur_x + delta_x > w) + { + cur_x = 0; + nb_lines++; + } + + /* update pointer */ + cur_x += delta_x; + } - lcd_getstringsize("A", &w, &h); - lines = (lcd? -#ifdef HAVE_REMOTE_LCD - LCD_REMOTE_HEIGHT -#else - 0 -#endif - :LCD_HEIGHT)/h; - columns = (lcd? -#ifdef HAVE_REMOTE_LCD - LCD_REMOTE_WIDTH -#else - 0 -#endif - :LCD_WIDTH)/w; + i++; + if(i >= MAX_LOGF_SIZE) + i = 0; + } while(i != logfindex); + + return nb_lines; +} - if (columns > MAX_LOGF_ENTRY+1) - columns = MAX_LOGF_ENTRY+1; - - if(!lines) - return false; +bool logfdisplay(void) +{ + int action; + int w, h, i, index; + int fontnr; + int cur_x, cur_y, delta_y, delta_x; + struct font* font; + int user_index;/* user_index will be number of the first line to display (warning: line!=logf entry) */ + char buf[2]; + + fontnr = lcd_getfont(); + font = font_get(fontnr); + + /* get the horizontal size of each line */ + font_getstringsize("A", NULL, &delta_y, fontnr); + + buf[1] = '\0'; + w = LCD_WIDTH; + h = LCD_HEIGHT; + /* start at the end of the log */ + user_index = compute_nb_lines(w, font) - h/delta_y -1; /* if negative, will be set 0 to zero later */ do { lcd_clear_display(); - index = logfindex + user_index; - for(i = lines-1; i>=0; i--) { - unsigned char buffer[columns + 1]; - - if(--index < 0) { - if(logfwrap) - index = MAX_LOGF_LINES-1; - else - break; /* done */ - } + if(user_index < 0) + user_index = 0; - memcpy(buffer, logfbuffer[index], columns); - if (logfbuffer[index][MAX_LOGF_ENTRY] == LOGF_TERMINATE_CONTINUE_LINE) - buffer[columns-1] = '>'; - else if (logfbuffer[index][MAX_LOGF_ENTRY] == LOGF_TERMINATE_MULTI_LINE) - buffer[columns-1] = '\0'; - buffer[columns] = '\0'; + if(logfwrap) + i = logfindex; + else + i = 0; - lcd_puts(0, i, buffer); - } + index = 0; + cur_x = 0; + cur_y = 0; + + /* nothing to print ? */ + if(logfindex == 0 && !logfwrap) + goto end_print; + + do { + if(logfbuffer[i] == '\0') + { + /* should be display a newline ? */ + if(index >= user_index) + cur_y += delta_y; + cur_x = 0; + index++; + } + else + { + /* does character fit on this line ? */ + delta_x = font_get_width(font, logfbuffer[i]); + + if(cur_x + delta_x > w) + { + /* should be display a newline ? */ + if(index >= user_index) + cur_y += delta_y; + cur_x = 0; + index++; + } + + /* should we print character ? */ + if(index >= user_index) + { + buf[0] = logfbuffer[i]; + lcd_putsxy(cur_x, cur_y, buf); + } + + /* update pointer */ + cur_x += delta_x; + } + + /* did we fill the screen ? */ + if(cur_y > h) + break; + + i++; + if(i >= MAX_LOGF_SIZE) + i = 0; + } while(i != logfindex); + + end_print: lcd_update(); action = get_action(CONTEXT_STD, HZ); - if(action == ACTION_STD_NEXT) - user_index++; - else if(action == ACTION_STD_PREV) - user_index--; - else if(action == ACTION_STD_OK) - user_index = 0; -#ifdef HAVE_TOUCHSCREEN - else if(action == ACTION_TOUCHSCREEN) + switch( action ) { - short x, y; - static int prev_y; - - action = action_get_touchscreen_press(&x, &y); - - if(action & BUTTON_REL) - prev_y = 0; - else + case ACTION_STD_NEXT: + case ACTION_STD_NEXTREPEAT: + user_index++; + break; + case ACTION_STD_PREV: + case ACTION_STD_PREVREPEAT: + user_index--; + break; + case ACTION_STD_OK: + user_index = 0; + break; +#ifdef HAVE_TOUCHSCREEN + case ACTION_TOUCHSCREEN: { - if(prev_y != 0) - user_index += (prev_y - y) / h; + short x, y; + static int prev_y; - prev_y = y; + action = action_get_touchscreen_press(&x, &y); + + if(action & BUTTON_REL) + prev_y = 0; + else + { + if(prev_y != 0) + user_index += (prev_y - y) / delta_y; + + prev_y = y; + } } - } #endif + default: + break; + } } while(action != ACTION_STD_CANCEL); return false; @@ -140,67 +225,31 @@ bool logfdump(void) { int fd; - if(!logfindex && !logfwrap) + /* nothing to print ? */ + if(logfindex == 0 && !logfwrap) /* nothing is logged just yet */ return false; fd = open(ROCKBOX_DIR "/logf.txt", O_CREAT|O_WRONLY|O_TRUNC); if(-1 != fd) { - unsigned char buffer[MAX_LOGF_ONE_LINE_SIZE +1]; - unsigned char *ptr; - int index = logfindex-1; - int stop = logfindex; - int tindex; - bool dumpwrap = false; - bool multiline; - - while(!dumpwrap || (index >= stop)) { - if(index < 0) { - if(logfwrap) - { - index = MAX_LOGF_LINES-1; - dumpwrap = true; - } - else - break; /* done */ - } - - multiline = false; - if (logfbuffer[index][MAX_LOGF_ENTRY] == LOGF_TERMINATE_MULTI_LINE) - { - multiline = true; - do { - index--; - if(index < 0) { - if(logfwrap) - { - index = MAX_LOGF_LINES-1; - dumpwrap = true; - } - else - goto end_loop; - } - } while(logfbuffer[index][MAX_LOGF_ENTRY] == LOGF_TERMINATE_CONTINUE_LINE); - index++; - if (index >= MAX_LOGF_LINES) - index = 0; - } - - tindex = index-1; - ptr = buffer; - do { - tindex++; - memcpy(ptr, logfbuffer[tindex], MAX_LOGF_ENTRY); - ptr += MAX_LOGF_ENTRY; - if (tindex >= MAX_LOGF_LINES) - tindex = 0; - } while(logfbuffer[tindex][MAX_LOGF_ENTRY] == LOGF_TERMINATE_CONTINUE_LINE); - *ptr = '\0'; + int i; + + if(logfwrap) + i = logfindex; + else + i = 0; + + do { + if(logfbuffer[i]=='\0') + fdprintf(fd, "\n"); + else + fdprintf(fd, "%c", logfbuffer[i]); + + i++; + if(i >= MAX_LOGF_SIZE) + i = 0; + } while(i != logfindex); - fdprintf(fd, "%s\n", buffer); - index--; - } -end_loop: close(fd); } return false; diff --git a/firmware/common/sprintf.c b/firmware/common/sprintf.c index 0f012f7340..6c1855e06b 100644 --- a/firmware/common/sprintf.c +++ b/firmware/common/sprintf.c @@ -292,3 +292,8 @@ int fdprintf(int fd, const char *fmt, ...) return fpr.bytes; /* return 0 on error */ } +int vfnprintf(int (*push)(void *userp, unsigned char data), void *userp, const char *fmt, va_list ap) +{ + return format(push, userp, fmt, ap); +} + diff --git a/firmware/export/logf.h b/firmware/export/logf.h index 4926fe5ef2..16666449d4 100644 --- a/firmware/export/logf.h +++ b/firmware/export/logf.h @@ -28,15 +28,10 @@ #ifdef ROCKBOX_HAS_LOGF #ifndef __PCTOOL__ -#define MAX_LOGF_LINES 1000 -#define MAX_LOGF_ENTRY 29 -#define MAX_LOGF_ONE_LINE_SIZE 200 -#define LOGF_TERMINATE_ONE_LINE 0x00 -#define LOGF_TERMINATE_CONTINUE_LINE 0x01 -#define LOGF_TERMINATE_MULTI_LINE 0x02 +#define MAX_LOGF_SIZE 16384 -extern unsigned char logfbuffer[MAX_LOGF_LINES][MAX_LOGF_ENTRY+1]; +extern unsigned char logfbuffer[MAX_LOGF_SIZE]; extern int logfindex; extern bool logfwrap; #endif /* __PCTOOL__ */ diff --git a/firmware/include/sprintf.h b/firmware/include/sprintf.h index ff9cf54d3a..b07ac9dfb6 100644 --- a/firmware/include/sprintf.h +++ b/firmware/include/sprintf.h @@ -32,4 +32,6 @@ int snprintf (char *buf, size_t size, const char *fmt, ...) int vsnprintf (char *buf, int size, const char *fmt, va_list ap); int fdprintf (int fd, const char *fmt, ...) ATTRIBUTE_PRINTF(2, 3); +int vfnprintf(int (*push)(void *userp, unsigned char data), void *userp, const char *fmt, va_list ap); + #endif /* __SPRINTF_H__ */ diff --git a/firmware/logf.c b/firmware/logf.c index 00fbfdc4b7..8817d4df45 100644 --- a/firmware/logf.c +++ b/firmware/logf.c @@ -20,28 +20,18 @@ ****************************************************************************/ /* - * logf() logs MAX_LOGF_ENTRY (29) bytes per entry in a circular buffer. Each - * logged string is space- padded for easier and faster output on screen. Just - * output MAX_LOGF_ENTRY characters on each line. MAX_LOGF_ENTRY bytes fit - * nicely on the iRiver remote LCD (128 pixels with an 8x6 pixels font). + * logf() logs entries in a circular buffer. Each logged string is null-terminated. * - * When the length of log exceeds MAX_LOGF_ENTRY bytes, dividing into the - * string of length is MAX_LOGF_ENTRY-1 bytes. + * When the length of log exceeds MAX_LOGF_SIZE bytes, the buffer wraps. * - * logfbuffer[*]: - * - * |<- MAX_LOGF_ENTRY bytes ->|1| - * | log data area |T| - * - * T : log terminate flag - * == LOGF_TERMINATE_ONE_LINE(0x00) : log data end (one line) - * == LOGF_TERMINATE_CONTINUE_LINE(0x01) : log data continues - * == LOGF_TERMINATE_MULTI_LINE(0x02) : log data end (multi line) */ #include #include #include +#include +#include +#include #include "config.h" #include "lcd-remote.h" #include "logf.h" @@ -56,7 +46,7 @@ #ifdef ROCKBOX_HAS_LOGF #ifndef __PCTOOL__ -unsigned char logfbuffer[MAX_LOGF_LINES][MAX_LOGF_ENTRY+1]; +unsigned char logfbuffer[MAX_LOGF_SIZE]; int logfindex; bool logfwrap; #endif @@ -65,32 +55,103 @@ bool logfwrap; static void displayremote(void) { /* TODO: we should have a debug option that enables/disables this! */ - int w, h; - int lines; - int columns; - int i; - int index; - - lcd_remote_getstringsize("A", &w, &h); - lines = LCD_REMOTE_HEIGHT/h; - columns = LCD_REMOTE_WIDTH/w; + int w, h, i; + int fontnr; + int cur_x, cur_y, delta_y, delta_x; + struct font* font; + int nb_lines; + char buf[2]; + /* Memorize the pointer to the beginning of the last ... lines + I assume delta_y >= 6 to avoid wasting memory and allocating memory dynamically + I hope there is no font with height < 6 ! */ + const int NB_ENTRIES=LCD_REMOTE_HEIGHT / 6; + int line_start_ptr[NB_ENTRIES]; + + fontnr = lcd_getfont(); + font = font_get(fontnr); + + /* get the horizontal size of each line */ + font_getstringsize("A", NULL, &delta_y, fontnr); + + /* font too small ? */ + if(delta_y < 6) + return; + /* nothing to print ? */ + if(logfindex == 0 && !logfwrap) + return; + + w = LCD_REMOTE_WIDTH; + h = LCD_REMOTE_HEIGHT; + nb_lines = 0; + + if(logfwrap) + i = logfindex; + else + i = 0; + + cur_x = 0; + + line_start_ptr[0] = i; + + do + { + if(logfbuffer[i] == '\0') + { + line_start_ptr[++nb_lines % NB_ENTRIES] = i+1; + cur_x = 0; + } + else + { + /* does character fit on this line ? */ + delta_x = font_get_width(font, logfbuffer[i]); + + if(cur_x + delta_x > w) + { + cur_x = 0; + line_start_ptr[++nb_lines % NB_ENTRIES] = i; + } + /* update pointer */ + cur_x += delta_x; + } + i++; + if(i >= MAX_LOGF_SIZE) + i = 0; + } while(i != logfindex); + lcd_remote_clear_display(); - index = logfindex; - for(i = lines-1; i>=0; i--) { - unsigned char buffer[columns+1]; - - if(--index < 0) { - if(logfwrap) - index = MAX_LOGF_LINES-1; - else - break; /* done */ + i = line_start_ptr[ MAX(nb_lines - h / delta_y, 0) % NB_ENTRIES]; + cur_x = 0; + cur_y = 0; + buf[1] = '\0'; + + do { + if(logfbuffer[i] == '\0') + { + cur_y += delta_y; + cur_x = 0; + } + else + { + /* does character fit on this line ? */ + delta_x = font_get_width(font, logfbuffer[i]); + + if(cur_x + delta_x > w) + { + cur_y += delta_y; + cur_x = 0; + } + + buf[0] = logfbuffer[i]; + lcd_remote_putsxy(cur_x, cur_y, buf); + cur_x += delta_x; } - memcpy(buffer, logfbuffer[index], columns); - buffer[columns]=0; - lcd_remote_puts(0, i, buffer); - } + i++; + if(i >= MAX_LOGF_SIZE) + i = 0; + } while(i != logfindex); + lcd_remote_update(); } #else @@ -110,59 +171,62 @@ void _logf(const char *format, ...) #else static void check_logfindex(void) { - if(logfindex >= MAX_LOGF_LINES) { + if(logfindex >= MAX_LOGF_SIZE) + { /* wrap */ logfwrap = true; logfindex = 0; } } -void _logf(const char *format, ...) +static int logf_push(void *userp, unsigned char c) { - int len; - int tlen; - unsigned char buf[MAX_LOGF_ONE_LINE_SIZE]; - unsigned char *ptr; + (void)userp; + + logfbuffer[logfindex++] = c; + check_logfindex(); + +#if defined(HAVE_SERIAL) && !defined(SIMULATOR) + if(c != '\0') + { + char buf[2]; + buf[0] = c; + buf[1] = '\0'; + serial_tx(buf); + } +#endif + + return true; +} + +void _logf(const char *fmt, ...) +{ + #ifdef USB_ENABLE_SERIAL + int old_logfindex = logfindex; + #endif va_list ap; - bool multiline = false; - va_start(ap, format); - vsnprintf(buf, MAX_LOGF_ONE_LINE_SIZE, format, ap); + va_start(ap, fmt); + vfnprintf(logf_push, NULL, fmt, ap); va_end(ap); - - len = strlen(buf); + + /* add trailing zero */ + logf_push(NULL, '\0'); + #if defined(HAVE_SERIAL) && !defined(SIMULATOR) - serial_tx(buf); serial_tx("\r\n"); #endif #ifdef USB_ENABLE_SERIAL - usb_serial_send(buf, len); - usb_serial_send("\r\n", 2); -#endif - tlen = 0; - check_logfindex(); - while(len > MAX_LOGF_ENTRY) + if(logfindex < old_logfindex) { - ptr = logfbuffer[logfindex]; - memcpy(ptr, buf + tlen, MAX_LOGF_ENTRY); - ptr[MAX_LOGF_ENTRY] = LOGF_TERMINATE_CONTINUE_LINE; - logfindex++; - check_logfindex(); - len -= MAX_LOGF_ENTRY; - tlen += MAX_LOGF_ENTRY; - multiline = true; + usb_serial_send(logfbuffer + old_logfindex, MAX_LOGF_SIZE - old_logfindex); + usb_serial_send(logfbuffer, logfindex - 1); } - - ptr = logfbuffer[logfindex]; - memcpy(ptr, buf + tlen,len); - - if(len < MAX_LOGF_ENTRY) - /* pad with spaces up to the MAX_LOGF_ENTRY byte border */ - memset(ptr+len, ' ', MAX_LOGF_ENTRY-len); - ptr[MAX_LOGF_ENTRY] = (multiline)?LOGF_TERMINATE_MULTI_LINE:LOGF_TERMINATE_ONE_LINE; - - logfindex++; /* leave it where we write the next time */ + else + usb_serial_send(logfbuffer + old_logfindex, logfindex - old_logfindex - 1); + usb_serial_send("\r\n", 2); +#endif displayremote(); } -- cgit v1.2.3