|
|
|
/* log.c */
|
|
|
|
|
|
|
|
#include "types.h"
|
|
|
|
#include "sdcard.h"
|
|
|
|
#include "uart.h"
|
|
|
|
#include "timer.h"
|
|
|
|
#include "log.h"
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
/* This is shared with sdcard.c */
|
|
|
|
bool log_enabled;
|
|
|
|
|
|
|
|
char log_buffer[LOG_BUFFERSIZE];
|
|
|
|
unsigned int log_bufferstart;
|
|
|
|
unsigned int log_bufferend;
|
|
|
|
|
|
|
|
unsigned int log_generation;
|
|
|
|
|
|
|
|
/* DO NOT call when the buffer is empty */
|
|
|
|
/* This should be safe against writes to the buffer, as the writes only
|
|
|
|
* affect log_bufferend. So no blocking of interrupts is necessary.
|
|
|
|
*/
|
|
|
|
char log_get_byte(void)
|
|
|
|
{
|
|
|
|
char i;
|
|
|
|
i = log_buffer[log_bufferstart++];
|
|
|
|
log_bufferstart = log_bufferstart % LOG_BUFFERSIZE;
|
|
|
|
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
|
|
|
void log_put_byte(char c)
|
|
|
|
{
|
|
|
|
if (!log_enabled)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* If the buffer is full, we just discard data.
|
|
|
|
* Better than overrunning.
|
|
|
|
*/
|
|
|
|
if (((log_bufferend + 1) % LOG_BUFFERSIZE) == log_bufferstart) {
|
|
|
|
#if 0
|
|
|
|
putstr("^");
|
|
|
|
#endif
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
log_buffer[log_bufferend++] = c;
|
|
|
|
log_bufferend = log_bufferend % LOG_BUFFERSIZE;
|
|
|
|
#if 0
|
|
|
|
putint(c);
|
|
|
|
putch(' ');
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void log_put_uint16(unsigned int i)
|
|
|
|
{
|
|
|
|
log_put_byte(i & 0xff);
|
|
|
|
log_put_byte((i >> 8) & 0xff);
|
|
|
|
}
|
|
|
|
|
|
|
|
void log_put_uint(unsigned int i)
|
|
|
|
{
|
|
|
|
log_put_byte(i & 0xff);
|
|
|
|
log_put_byte((i >> 8) & 0xff);
|
|
|
|
log_put_byte((i >> 16) & 0xff);
|
|
|
|
log_put_byte((i >> 24) & 0xff);
|
|
|
|
}
|
|
|
|
|
|
|
|
void log_put_header(unsigned int timestamp)
|
|
|
|
{
|
|
|
|
log_put_uint(LOG_MAGIC);
|
|
|
|
log_put_uint(log_generation);
|
|
|
|
log_put_uint(timestamp);
|
|
|
|
log_put_uint(log_read_busytime());
|
|
|
|
}
|
|
|
|
|
|
|
|
void log_put_config(void)
|
|
|
|
{
|
|
|
|
log_put_uint(LOG_MAGIC_CONFIG);
|
|
|
|
log_put_uint(CONFIG_VERSION);
|
|
|
|
log_put_uint(sizeof(struct config));
|
|
|
|
log_put_array((char *)&config, sizeof(struct config));
|
|
|
|
}
|
|
|
|
|
|
|
|
void log_put_array(char *data, int length)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < length; i++)
|
|
|
|
log_put_byte(data[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
void log_put_float(float f)
|
|
|
|
{
|
|
|
|
union {
|
|
|
|
float f;
|
|
|
|
unsigned int i;
|
|
|
|
} data;
|
|
|
|
data.f = f;
|
|
|
|
log_put_uint(data.i);
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned int log_busystamp;
|
|
|
|
unsigned int log_busytime;
|
|
|
|
|
|
|
|
void log_mark_busy(void)
|
|
|
|
{
|
|
|
|
unsigned int time = timer_read();
|
|
|
|
log_busystamp = time;
|
|
|
|
}
|
|
|
|
|
|
|
|
void log_mark_idle(void)
|
|
|
|
{
|
|
|
|
unsigned int time = timer_read();
|
|
|
|
unsigned int diff = time - log_busystamp;
|
|
|
|
log_busytime += diff;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned int log_read_busytime(void)
|
|
|
|
{
|
|
|
|
unsigned int time = log_busytime;
|
|
|
|
log_busytime = 0;
|
|
|
|
return time;
|
|
|
|
}
|