b8a51adb57
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@26042 a1c6a512-1295-4272-9138-f99709370657
242 lines
5.5 KiB
C
242 lines
5.5 KiB
C
/***************************************************************************
|
|
* __________ __ ___.
|
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
|
* \/ \/ \/ \/ \/
|
|
* $Id$
|
|
*
|
|
* Copyright (C) 2005 by Daniel Stenberg
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
|
* KIND, either express or implied.
|
|
*
|
|
****************************************************************************/
|
|
|
|
/*
|
|
* logf() logs entries in a circular buffer. Each logged string is null-terminated.
|
|
*
|
|
* When the length of log exceeds MAX_LOGF_SIZE bytes, the buffer wraps.
|
|
*
|
|
*/
|
|
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include <stdarg.h>
|
|
#include "config.h"
|
|
#include "system.h"
|
|
#include "font.h"
|
|
#include "lcd-remote.h"
|
|
#include "logf.h"
|
|
#include "serial.h"
|
|
#include "format.h"
|
|
|
|
#ifdef HAVE_USBSTACK
|
|
#include "usb_core.h"
|
|
#include "usbstack/usb_serial.h"
|
|
#endif
|
|
|
|
/* Only provide all this if asked to */
|
|
#ifdef ROCKBOX_HAS_LOGF
|
|
|
|
#ifndef __PCTOOL__
|
|
unsigned char logfbuffer[MAX_LOGF_SIZE];
|
|
int logfindex;
|
|
bool logfwrap;
|
|
#endif
|
|
|
|
#ifdef HAVE_REMOTE_LCD
|
|
static void displayremote(void)
|
|
{
|
|
/* TODO: we should have a debug option that enables/disables this! */
|
|
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();
|
|
|
|
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;
|
|
}
|
|
|
|
i++;
|
|
if(i >= MAX_LOGF_SIZE)
|
|
i = 0;
|
|
} while(i != logfindex);
|
|
|
|
lcd_remote_update();
|
|
}
|
|
#else
|
|
#define displayremote()
|
|
#endif
|
|
|
|
#ifdef __PCTOOL__
|
|
void _logf(const char *format, ...)
|
|
{
|
|
char buf[1024];
|
|
va_list ap;
|
|
va_start(ap, format);
|
|
|
|
vsnprintf(buf, sizeof buf, format, ap);
|
|
printf("DEBUG: %s\n", buf);
|
|
}
|
|
#else
|
|
static void check_logfindex(void)
|
|
{
|
|
if(logfindex >= MAX_LOGF_SIZE)
|
|
{
|
|
/* wrap */
|
|
logfwrap = true;
|
|
logfindex = 0;
|
|
}
|
|
}
|
|
|
|
static int logf_push(void *userp, unsigned char c)
|
|
{
|
|
(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;
|
|
|
|
va_start(ap, fmt);
|
|
|
|
#ifdef SIMULATOR
|
|
char buf[1024];
|
|
vsnprintf(buf, sizeof buf, fmt, ap);
|
|
DEBUGF("%s\n", buf);
|
|
#endif
|
|
|
|
vuprintf(logf_push, NULL, fmt, ap);
|
|
va_end(ap);
|
|
|
|
/* add trailing zero */
|
|
logf_push(NULL, '\0');
|
|
|
|
#if defined(HAVE_SERIAL) && !defined(SIMULATOR)
|
|
serial_tx("\r\n");
|
|
#endif
|
|
#ifdef USB_ENABLE_SERIAL
|
|
|
|
if(logfindex < old_logfindex)
|
|
{
|
|
usb_serial_send(logfbuffer + old_logfindex, MAX_LOGF_SIZE - old_logfindex);
|
|
usb_serial_send(logfbuffer, logfindex - 1);
|
|
}
|
|
else
|
|
usb_serial_send(logfbuffer + old_logfindex, logfindex - old_logfindex - 1);
|
|
usb_serial_send("\r\n", 2);
|
|
#endif
|
|
|
|
displayremote();
|
|
}
|
|
#endif
|
|
|
|
#endif
|