/* log.c */

#include "types.h"
#include "sdcard.h"
#include "uart.h"
#include "timer.h"
#include "log.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)
		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_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;
}
