summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaurus Cuelenaere <mcuelenaere@gmail.com>2009-08-21 22:54:23 +0000
committerMaurus Cuelenaere <mcuelenaere@gmail.com>2009-08-21 22:54:23 +0000
commit20b0dd2788794521ac7f3eec1065b7de99e4a5aa (patch)
treeef44f6d28e4674e6a4dda8e36187e9723186cb2e
parent249392c2d33130b86e39ad36d99cc2673842e37d (diff)
downloadrockbox-20b0dd2788794521ac7f3eec1065b7de99e4a5aa.zip
rockbox-20b0dd2788794521ac7f3eec1065b7de99e4a5aa.tar.gz
rockbox-20b0dd2788794521ac7f3eec1065b7de99e4a5aa.tar.bz2
rockbox-20b0dd2788794521ac7f3eec1065b7de99e4a5aa.tar.xz
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
-rw-r--r--apps/logfdisp.c293
-rw-r--r--firmware/common/sprintf.c5
-rw-r--r--firmware/export/logf.h9
-rw-r--r--firmware/include/sprintf.h2
-rw-r--r--firmware/logf.c212
5 files changed, 318 insertions, 203 deletions
diff --git a/apps/logfdisp.c b/apps/logfdisp.c
index da711bf..41cb109 100644
--- a/apps/logfdisp.c
+++ b/apps/logfdisp.c
@@ -29,6 +29,7 @@
#include <action.h>
#include <lcd.h>
+#include <font.h>
#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 0f012f7..6c1855e 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 4926fe5..1666644 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 ff9cf54..b07ac9d 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 00fbfdc..8817d4d 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 <string.h>
#include <stdio.h>
#include <stdarg.h>
+#include <sprintf.h>
+#include <system.h>
+#include <font.h>
#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();
}