summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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 da711bf1d3..41cb109efd 100644
--- a/apps/logfdisp.c
+++ b/apps/logfdisp.c
@@ -29,6 +29,7 @@
29#include <action.h> 29#include <action.h>
30 30
31#include <lcd.h> 31#include <lcd.h>
32#include <font.h>
32#include "menu.h" 33#include "menu.h"
33#include "logf.h" 34#include "logf.h"
34#include "settings.h" 35#include "settings.h"
@@ -36,90 +37,174 @@
36#include "action.h" 37#include "action.h"
37 38
38#ifdef HAVE_LCD_BITMAP 39#ifdef HAVE_LCD_BITMAP
39bool logfdisplay(void) 40int compute_nb_lines(int w, struct font* font)
40{ 41{
41 int w, h; 42 int i, nb_lines;
42 int lines; 43 int cur_x, delta_x;
43 int columns; 44
44 int i; 45 if(logfindex == 0 && !logfwrap)
45 int action; 46 return 0;
46 47
47 bool lcd = false; /* fixed atm */ 48 if(logfwrap)
48 int index, user_index=0; 49 i = logfindex;
50 else
51 i = 0;
52
53 cur_x = 0;
54 nb_lines = 0;
55
56 do {
57 if(logfbuffer[i] == '\0')
58 {
59 cur_x = 0;
60 nb_lines++;
61 }
62 else
63 {
64 /* does character fit on this line ? */
65 delta_x = font_get_width(font, logfbuffer[i]);
66
67 if(cur_x + delta_x > w)
68 {
69 cur_x = 0;
70 nb_lines++;
71 }
72
73 /* update pointer */
74 cur_x += delta_x;
75 }
49 76
50 lcd_getstringsize("A", &w, &h); 77 i++;
51 lines = (lcd? 78 if(i >= MAX_LOGF_SIZE)
52#ifdef HAVE_REMOTE_LCD 79 i = 0;
53 LCD_REMOTE_HEIGHT 80 } while(i != logfindex);
54#else 81
55 0 82 return nb_lines;
56#endif 83}
57 :LCD_HEIGHT)/h;
58 columns = (lcd?
59#ifdef HAVE_REMOTE_LCD
60 LCD_REMOTE_WIDTH
61#else
62 0
63#endif
64 :LCD_WIDTH)/w;
65 84
66 if (columns > MAX_LOGF_ENTRY+1) 85bool logfdisplay(void)
67 columns = MAX_LOGF_ENTRY+1; 86{
68 87 int action;
69 if(!lines) 88 int w, h, i, index;
70 return false; 89 int fontnr;
90 int cur_x, cur_y, delta_y, delta_x;
91 struct font* font;
92 int user_index;/* user_index will be number of the first line to display (warning: line!=logf entry) */
93 char buf[2];
94
95 fontnr = lcd_getfont();
96 font = font_get(fontnr);
97
98 /* get the horizontal size of each line */
99 font_getstringsize("A", NULL, &delta_y, fontnr);
100
101 buf[1] = '\0';
102 w = LCD_WIDTH;
103 h = LCD_HEIGHT;
104 /* start at the end of the log */
105 user_index = compute_nb_lines(w, font) - h/delta_y -1; /* if negative, will be set 0 to zero later */
71 106
72 do { 107 do {
73 lcd_clear_display(); 108 lcd_clear_display();
74 109
75 index = logfindex + user_index; 110 if(user_index < 0)
76 for(i = lines-1; i>=0; i--) { 111 user_index = 0;
77 unsigned char buffer[columns + 1];
78
79 if(--index < 0) {
80 if(logfwrap)
81 index = MAX_LOGF_LINES-1;
82 else
83 break; /* done */
84 }
85 112
86 memcpy(buffer, logfbuffer[index], columns); 113 if(logfwrap)
87 if (logfbuffer[index][MAX_LOGF_ENTRY] == LOGF_TERMINATE_CONTINUE_LINE) 114 i = logfindex;
88 buffer[columns-1] = '>'; 115 else
89 else if (logfbuffer[index][MAX_LOGF_ENTRY] == LOGF_TERMINATE_MULTI_LINE) 116 i = 0;
90 buffer[columns-1] = '\0';
91 buffer[columns] = '\0';
92 117
93 lcd_puts(0, i, buffer); 118 index = 0;
94 } 119 cur_x = 0;
120 cur_y = 0;
121
122 /* nothing to print ? */
123 if(logfindex == 0 && !logfwrap)
124 goto end_print;
125
126 do {
127 if(logfbuffer[i] == '\0')
128 {
129 /* should be display a newline ? */
130 if(index >= user_index)
131 cur_y += delta_y;
132 cur_x = 0;
133 index++;
134 }
135 else
136 {
137 /* does character fit on this line ? */
138 delta_x = font_get_width(font, logfbuffer[i]);
139
140 if(cur_x + delta_x > w)
141 {
142 /* should be display a newline ? */
143 if(index >= user_index)
144 cur_y += delta_y;
145 cur_x = 0;
146 index++;
147 }
148
149 /* should we print character ? */
150 if(index >= user_index)
151 {
152 buf[0] = logfbuffer[i];
153 lcd_putsxy(cur_x, cur_y, buf);
154 }
155
156 /* update pointer */
157 cur_x += delta_x;
158 }
159
160 /* did we fill the screen ? */
161 if(cur_y > h)
162 break;
163
164 i++;
165 if(i >= MAX_LOGF_SIZE)
166 i = 0;
167 } while(i != logfindex);
168
169 end_print:
95 lcd_update(); 170 lcd_update();
96 171
97 action = get_action(CONTEXT_STD, HZ); 172 action = get_action(CONTEXT_STD, HZ);
98 if(action == ACTION_STD_NEXT) 173 switch( action )
99 user_index++;
100 else if(action == ACTION_STD_PREV)
101 user_index--;
102 else if(action == ACTION_STD_OK)
103 user_index = 0;
104#ifdef HAVE_TOUCHSCREEN
105 else if(action == ACTION_TOUCHSCREEN)
106 { 174 {
107 short x, y; 175 case ACTION_STD_NEXT:
108 static int prev_y; 176 case ACTION_STD_NEXTREPEAT:
109 177 user_index++;
110 action = action_get_touchscreen_press(&x, &y); 178 break;
111 179 case ACTION_STD_PREV:
112 if(action & BUTTON_REL) 180 case ACTION_STD_PREVREPEAT:
113 prev_y = 0; 181 user_index--;
114 else 182 break;
183 case ACTION_STD_OK:
184 user_index = 0;
185 break;
186#ifdef HAVE_TOUCHSCREEN
187 case ACTION_TOUCHSCREEN:
115 { 188 {
116 if(prev_y != 0) 189 short x, y;
117 user_index += (prev_y - y) / h; 190 static int prev_y;
118 191
119 prev_y = y; 192 action = action_get_touchscreen_press(&x, &y);
193
194 if(action & BUTTON_REL)
195 prev_y = 0;
196 else
197 {
198 if(prev_y != 0)
199 user_index += (prev_y - y) / delta_y;
200
201 prev_y = y;
202 }
120 } 203 }
121 }
122#endif 204#endif
205 default:
206 break;
207 }
123 } while(action != ACTION_STD_CANCEL); 208 } while(action != ACTION_STD_CANCEL);
124 209
125 return false; 210 return false;
@@ -140,67 +225,31 @@ bool logfdump(void)
140{ 225{
141 int fd; 226 int fd;
142 227
143 if(!logfindex && !logfwrap) 228 /* nothing to print ? */
229 if(logfindex == 0 && !logfwrap)
144 /* nothing is logged just yet */ 230 /* nothing is logged just yet */
145 return false; 231 return false;
146 232
147 fd = open(ROCKBOX_DIR "/logf.txt", O_CREAT|O_WRONLY|O_TRUNC); 233 fd = open(ROCKBOX_DIR "/logf.txt", O_CREAT|O_WRONLY|O_TRUNC);
148 if(-1 != fd) { 234 if(-1 != fd) {
149 unsigned char buffer[MAX_LOGF_ONE_LINE_SIZE +1]; 235 int i;
150 unsigned char *ptr; 236
151 int index = logfindex-1; 237 if(logfwrap)
152 int stop = logfindex; 238 i = logfindex;
153 int tindex; 239 else
154 bool dumpwrap = false; 240 i = 0;
155 bool multiline; 241
156 242 do {
157 while(!dumpwrap || (index >= stop)) { 243 if(logfbuffer[i]=='\0')
158 if(index < 0) { 244 fdprintf(fd, "\n");
159 if(logfwrap) 245 else
160 { 246 fdprintf(fd, "%c", logfbuffer[i]);
161 index = MAX_LOGF_LINES-1; 247
162 dumpwrap = true; 248 i++;
163 } 249 if(i >= MAX_LOGF_SIZE)
164 else 250 i = 0;
165 break; /* done */ 251 } while(i != logfindex);
166 }
167
168 multiline = false;
169 if (logfbuffer[index][MAX_LOGF_ENTRY] == LOGF_TERMINATE_MULTI_LINE)
170 {
171 multiline = true;
172 do {
173 index--;
174 if(index < 0) {
175 if(logfwrap)
176 {
177 index = MAX_LOGF_LINES-1;
178 dumpwrap = true;
179 }
180 else
181 goto end_loop;
182 }
183 } while(logfbuffer[index][MAX_LOGF_ENTRY] == LOGF_TERMINATE_CONTINUE_LINE);
184 index++;
185 if (index >= MAX_LOGF_LINES)
186 index = 0;
187 }
188
189 tindex = index-1;
190 ptr = buffer;
191 do {
192 tindex++;
193 memcpy(ptr, logfbuffer[tindex], MAX_LOGF_ENTRY);
194 ptr += MAX_LOGF_ENTRY;
195 if (tindex >= MAX_LOGF_LINES)
196 tindex = 0;
197 } while(logfbuffer[tindex][MAX_LOGF_ENTRY] == LOGF_TERMINATE_CONTINUE_LINE);
198 *ptr = '\0';
199 252
200 fdprintf(fd, "%s\n", buffer);
201 index--;
202 }
203end_loop:
204 close(fd); 253 close(fd);
205 } 254 }
206 return false; 255 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, ...)
292 return fpr.bytes; /* return 0 on error */ 292 return fpr.bytes; /* return 0 on error */
293} 293}
294 294
295int vfnprintf(int (*push)(void *userp, unsigned char data), void *userp, const char *fmt, va_list ap)
296{
297 return format(push, userp, fmt, ap);
298}
299
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 @@
28#ifdef ROCKBOX_HAS_LOGF 28#ifdef ROCKBOX_HAS_LOGF
29 29
30#ifndef __PCTOOL__ 30#ifndef __PCTOOL__
31#define MAX_LOGF_LINES 1000
32#define MAX_LOGF_ENTRY 29
33#define MAX_LOGF_ONE_LINE_SIZE 200
34 31
35#define LOGF_TERMINATE_ONE_LINE 0x00 32#define MAX_LOGF_SIZE 16384
36#define LOGF_TERMINATE_CONTINUE_LINE 0x01
37#define LOGF_TERMINATE_MULTI_LINE 0x02
38 33
39extern unsigned char logfbuffer[MAX_LOGF_LINES][MAX_LOGF_ENTRY+1]; 34extern unsigned char logfbuffer[MAX_LOGF_SIZE];
40extern int logfindex; 35extern int logfindex;
41extern bool logfwrap; 36extern bool logfwrap;
42#endif /* __PCTOOL__ */ 37#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, ...)
32int vsnprintf (char *buf, int size, const char *fmt, va_list ap); 32int vsnprintf (char *buf, int size, const char *fmt, va_list ap);
33int fdprintf (int fd, const char *fmt, ...) ATTRIBUTE_PRINTF(2, 3); 33int fdprintf (int fd, const char *fmt, ...) ATTRIBUTE_PRINTF(2, 3);
34 34
35int vfnprintf(int (*push)(void *userp, unsigned char data), void *userp, const char *fmt, va_list ap);
36
35#endif /* __SPRINTF_H__ */ 37#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 @@
20 ****************************************************************************/ 20 ****************************************************************************/
21 21
22/* 22/*
23 * logf() logs MAX_LOGF_ENTRY (29) bytes per entry in a circular buffer. Each 23 * logf() logs entries in a circular buffer. Each logged string is null-terminated.
24 * logged string is space- padded for easier and faster output on screen. Just
25 * output MAX_LOGF_ENTRY characters on each line. MAX_LOGF_ENTRY bytes fit
26 * nicely on the iRiver remote LCD (128 pixels with an 8x6 pixels font).
27 * 24 *
28 * When the length of log exceeds MAX_LOGF_ENTRY bytes, dividing into the 25 * When the length of log exceeds MAX_LOGF_SIZE bytes, the buffer wraps.
29 * string of length is MAX_LOGF_ENTRY-1 bytes.
30 * 26 *
31 * logfbuffer[*]:
32 *
33 * |<- MAX_LOGF_ENTRY bytes ->|1|
34 * | log data area |T|
35 *
36 * T : log terminate flag
37 * == LOGF_TERMINATE_ONE_LINE(0x00) : log data end (one line)
38 * == LOGF_TERMINATE_CONTINUE_LINE(0x01) : log data continues
39 * == LOGF_TERMINATE_MULTI_LINE(0x02) : log data end (multi line)
40 */ 27 */
41 28
42#include <string.h> 29#include <string.h>
43#include <stdio.h> 30#include <stdio.h>
44#include <stdarg.h> 31#include <stdarg.h>
32#include <sprintf.h>
33#include <system.h>
34#include <font.h>
45#include "config.h" 35#include "config.h"
46#include "lcd-remote.h" 36#include "lcd-remote.h"
47#include "logf.h" 37#include "logf.h"
@@ -56,7 +46,7 @@
56#ifdef ROCKBOX_HAS_LOGF 46#ifdef ROCKBOX_HAS_LOGF
57 47
58#ifndef __PCTOOL__ 48#ifndef __PCTOOL__
59unsigned char logfbuffer[MAX_LOGF_LINES][MAX_LOGF_ENTRY+1]; 49unsigned char logfbuffer[MAX_LOGF_SIZE];
60int logfindex; 50int logfindex;
61bool logfwrap; 51bool logfwrap;
62#endif 52#endif
@@ -65,32 +55,103 @@ bool logfwrap;
65static void displayremote(void) 55static void displayremote(void)
66{ 56{
67 /* TODO: we should have a debug option that enables/disables this! */ 57 /* TODO: we should have a debug option that enables/disables this! */
68 int w, h; 58 int w, h, i;
69 int lines; 59 int fontnr;
70 int columns; 60 int cur_x, cur_y, delta_y, delta_x;
71 int i; 61 struct font* font;
72 int index; 62 int nb_lines;
73 63 char buf[2];
74 lcd_remote_getstringsize("A", &w, &h); 64 /* Memorize the pointer to the beginning of the last ... lines
75 lines = LCD_REMOTE_HEIGHT/h; 65 I assume delta_y >= 6 to avoid wasting memory and allocating memory dynamically
76 columns = LCD_REMOTE_WIDTH/w; 66 I hope there is no font with height < 6 ! */
67 const int NB_ENTRIES=LCD_REMOTE_HEIGHT / 6;
68 int line_start_ptr[NB_ENTRIES];
69
70 fontnr = lcd_getfont();
71 font = font_get(fontnr);
72
73 /* get the horizontal size of each line */
74 font_getstringsize("A", NULL, &delta_y, fontnr);
75
76 /* font too small ? */
77 if(delta_y < 6)
78 return;
79 /* nothing to print ? */
80 if(logfindex == 0 && !logfwrap)
81 return;
82
83 w = LCD_REMOTE_WIDTH;
84 h = LCD_REMOTE_HEIGHT;
85 nb_lines = 0;
86
87 if(logfwrap)
88 i = logfindex;
89 else
90 i = 0;
91
92 cur_x = 0;
93
94 line_start_ptr[0] = i;
95
96 do
97 {
98 if(logfbuffer[i] == '\0')
99 {
100 line_start_ptr[++nb_lines % NB_ENTRIES] = i+1;
101 cur_x = 0;
102 }
103 else
104 {
105 /* does character fit on this line ? */
106 delta_x = font_get_width(font, logfbuffer[i]);
107
108 if(cur_x + delta_x > w)
109 {
110 cur_x = 0;
111 line_start_ptr[++nb_lines % NB_ENTRIES] = i;
112 }
113 /* update pointer */
114 cur_x += delta_x;
115 }
116 i++;
117 if(i >= MAX_LOGF_SIZE)
118 i = 0;
119 } while(i != logfindex);
120
77 lcd_remote_clear_display(); 121 lcd_remote_clear_display();
78 122
79 index = logfindex; 123 i = line_start_ptr[ MAX(nb_lines - h / delta_y, 0) % NB_ENTRIES];
80 for(i = lines-1; i>=0; i--) { 124 cur_x = 0;
81 unsigned char buffer[columns+1]; 125 cur_y = 0;
82 126 buf[1] = '\0';
83 if(--index < 0) { 127
84 if(logfwrap) 128 do {
85 index = MAX_LOGF_LINES-1; 129 if(logfbuffer[i] == '\0')
86 else 130 {
87 break; /* done */ 131 cur_y += delta_y;
132 cur_x = 0;
133 }
134 else
135 {
136 /* does character fit on this line ? */
137 delta_x = font_get_width(font, logfbuffer[i]);
138
139 if(cur_x + delta_x > w)
140 {
141 cur_y += delta_y;
142 cur_x = 0;
143 }
144
145 buf[0] = logfbuffer[i];
146 lcd_remote_putsxy(cur_x, cur_y, buf);
147 cur_x += delta_x;
88 } 148 }
89 149
90 memcpy(buffer, logfbuffer[index], columns); 150 i++;
91 buffer[columns]=0; 151 if(i >= MAX_LOGF_SIZE)
92 lcd_remote_puts(0, i, buffer); 152 i = 0;
93 } 153 } while(i != logfindex);
154
94 lcd_remote_update(); 155 lcd_remote_update();
95} 156}
96#else 157#else
@@ -110,59 +171,62 @@ void _logf(const char *format, ...)
110#else 171#else
111static void check_logfindex(void) 172static void check_logfindex(void)
112{ 173{
113 if(logfindex >= MAX_LOGF_LINES) { 174 if(logfindex >= MAX_LOGF_SIZE)
175 {
114 /* wrap */ 176 /* wrap */
115 logfwrap = true; 177 logfwrap = true;
116 logfindex = 0; 178 logfindex = 0;
117 } 179 }
118} 180}
119 181
120void _logf(const char *format, ...) 182static int logf_push(void *userp, unsigned char c)
121{ 183{
122 int len; 184 (void)userp;
123 int tlen; 185
124 unsigned char buf[MAX_LOGF_ONE_LINE_SIZE]; 186 logfbuffer[logfindex++] = c;
125 unsigned char *ptr; 187 check_logfindex();
188
189#if defined(HAVE_SERIAL) && !defined(SIMULATOR)
190 if(c != '\0')
191 {
192 char buf[2];
193 buf[0] = c;
194 buf[1] = '\0';
195 serial_tx(buf);
196 }
197#endif
198
199 return true;
200}
201
202void _logf(const char *fmt, ...)
203{
204 #ifdef USB_ENABLE_SERIAL
205 int old_logfindex = logfindex;
206 #endif
126 va_list ap; 207 va_list ap;
127 bool multiline = false;
128 208
129 va_start(ap, format); 209 va_start(ap, fmt);
130 vsnprintf(buf, MAX_LOGF_ONE_LINE_SIZE, format, ap); 210 vfnprintf(logf_push, NULL, fmt, ap);
131 va_end(ap); 211 va_end(ap);
132 212
133 len = strlen(buf); 213 /* add trailing zero */
214 logf_push(NULL, '\0');
215
134#if defined(HAVE_SERIAL) && !defined(SIMULATOR) 216#if defined(HAVE_SERIAL) && !defined(SIMULATOR)
135 serial_tx(buf);
136 serial_tx("\r\n"); 217 serial_tx("\r\n");
137#endif 218#endif
138#ifdef USB_ENABLE_SERIAL 219#ifdef USB_ENABLE_SERIAL
139 usb_serial_send(buf, len);
140 usb_serial_send("\r\n", 2);
141#endif
142 220
143 tlen = 0; 221 if(logfindex < old_logfindex)
144 check_logfindex();
145 while(len > MAX_LOGF_ENTRY)
146 { 222 {
147 ptr = logfbuffer[logfindex]; 223 usb_serial_send(logfbuffer + old_logfindex, MAX_LOGF_SIZE - old_logfindex);
148 memcpy(ptr, buf + tlen, MAX_LOGF_ENTRY); 224 usb_serial_send(logfbuffer, logfindex - 1);
149 ptr[MAX_LOGF_ENTRY] = LOGF_TERMINATE_CONTINUE_LINE;
150 logfindex++;
151 check_logfindex();
152 len -= MAX_LOGF_ENTRY;
153 tlen += MAX_LOGF_ENTRY;
154 multiline = true;
155 } 225 }
156 226 else
157 ptr = logfbuffer[logfindex]; 227 usb_serial_send(logfbuffer + old_logfindex, logfindex - old_logfindex - 1);
158 memcpy(ptr, buf + tlen,len); 228 usb_serial_send("\r\n", 2);
159 229#endif
160 if(len < MAX_LOGF_ENTRY)
161 /* pad with spaces up to the MAX_LOGF_ENTRY byte border */
162 memset(ptr+len, ' ', MAX_LOGF_ENTRY-len);
163 ptr[MAX_LOGF_ENTRY] = (multiline)?LOGF_TERMINATE_MULTI_LINE:LOGF_TERMINATE_ONE_LINE;
164
165 logfindex++; /* leave it where we write the next time */
166 230
167 displayremote(); 231 displayremote();
168} 232}