Files @ 6ab6b1fe2314
Branch filter:

Location: seniordesign-firmware/master/master/lib/logger.c

ethanzonca@CL-ENS241-08.cedarville.edu
Added InfoText logger for generic informational messages, GPS fix light now reports 3d location fixes, log is made when fix is acquired/lost. Added maximum retransmission limit.
/*
 * Master Firmware: SD Card Data Logger
 *
 * Wireless Observational Modular Aerial Network
 * 
 * Ethan Zonca
 * Matthew Kanning
 * Kyle Ripperger
 * Matthew Kroening
 *
 */

#include "../config.h"
#include <util/delay.h>
#include <string.h>
#include <stdio.h>
#include <avr/pgmspace.h>
#include <avr/sleep.h>
#include <avr/eeprom.h>
#include <string.h>
#include "sdcard/fat.h"
#include "sdcard/fat_config.h"
#include "sdcard/partition.h"
#include "sdcard/sd_raw.h"
#include "sdcard/sd_raw_config.h"
#include "serial.h"
#include "logger.h"
#include "led.h"
#include "looptime.h"

#define MAX_ERRNO 8

// Label lookup table
// Make sure there are never more labels than there are MAX_NUM_SENSORS!
const char err_0[] PROGMEM = "slave timeout";
const char err_1[] PROGMEM = "initializing SD card failed";
const char err_2[] PROGMEM = "opening SD partition failed";
const char err_3[] PROGMEM = "opening SD file failed";
const char err_4[] PROGMEM = "XBee timeout";
const char err_5[] PROGMEM = "FATAL UNHANDLED ERROR";
const char err_6[] PROGMEM = "enter AT mode failed";
const char err_7[] PROGMEM = "exit AT mode failed";
const char err_8[] PROGMEM = "infotext";

const char *const errorMessageLookup[] PROGMEM =
{
	err_0,
	err_1,
	err_2,
	err_3,
	err_4,
	err_5,
	err_6,
	err_7,
	err_8,
};



struct partition_struct* partition;
struct fat_fs_struct* fs;
struct fat_dir_struct* dd;
struct fat_file_struct* fd_datalog;
struct fat_file_struct* fd_errorlog;

void logger_setup()
{

	if(!sd_raw_init())
	{
		error_log(ERROR_SD_INIT, true);
		return;
	}

	// TODO: Check SD card switch to see if inserted.
	// this was included in the library, but is commented out right now
	
	// Open first partition
	partition = partition_open(sd_raw_read, sd_raw_read_interval, sd_raw_write, sd_raw_write_interval, 0);
	
	// Check that partition was created correctly
	if(!partition)
	{
		// Error opening partition. MBR might be screwed up.
		error_log(ERROR_SD_PARTITION, true);
		return;
	}
	
	
	// Open FAT filesystem
	fs = fat_open(partition);
	if(!fs)
	{
		// opening filesystem failed
		error_log(ERROR_SD_PARTITION, true);
		return;
	}
	
	// Open root directory
	struct fat_dir_entry_struct rootDirEntry;
	fat_get_dir_entry_of_path(fs, "/", &rootDirEntry);

	dd = fat_open_dir(fs, &rootDirEntry);
	if(!dd)
	{
		// opening root directory failed
		_delay_ms(10);
		error_log(ERROR_SD_FILE, true);
		return;
	}
	
		
	// we pre-increment logid here because it starts at 255, then wraps to 0
	uint8_t logid = eeprom_read_byte(LOGGER_ID_EEPROM_ADDR) + 1;
	eeprom_update_byte(LOGGER_ID_EEPROM_ADDR, logid);
	
	int32_t errorOffset = 0;
	char errorFilename[17];
	
	
	// Form filename
	snprintf(errorFilename, 17, "run%derror.csv",logid);
	struct fat_dir_entry_struct errorDirEntry;
	if(fat_create_file(dd, errorFilename, &errorDirEntry) == 0)
	{
		serial0_sendString("Error create errorlog\r\n");
		error_log(ERROR_SD_FILE, true);
	}
	// Search for file in current directory and open it
	fd_errorlog = open_file_in_dir(fs, dd, errorFilename);
	if(!fd_errorlog)
	{
		serial0_sendString("Error open errorlog!\r\n");
		error_log(ERROR_SD_FILE, true);
		return;
	}
	errorOffset=0;
	if(!fat_seek_file(fd_errorlog, &errorOffset, FAT_SEEK_SET))
	{
		// Error seeking to file
		serial0_sendString("Error seek errorlog!\r\n");
		error_log(ERROR_SD_FILE, true);
		fat_close_file(fd_errorlog);
		return;
	}
	
		
	int32_t dataOffset = 0;
	char dataFilename[17];
	
	// Form filename
	snprintf(dataFilename, 17, "run%ddata.csv",logid);
	struct fat_dir_entry_struct dataDirEntry;
	// Create new data log file
	if(fat_create_file(dd, dataFilename, &dataDirEntry) == 0) 
	{
		serial0_sendString("Error create datalog\r\n");
		error_log(ERROR_SD_FILE, true);
	}
	// Search for file in current directory and open it
	fd_datalog = open_file_in_dir(fs, dd, dataFilename);
	if(!fd_datalog)
	{
		serial0_sendString("Error open datalog!\r\n");
		error_log(ERROR_SD_FILE, true);
		return;
	}
	dataOffset=0;
	if(!fat_seek_file(fd_datalog, &dataOffset, FAT_SEEK_SET))
	{
		// Error seeking to file
		serial0_sendString("Error seek datalog!\r\n");
		error_log(ERROR_SD_FILE, true);
		fat_close_file(fd_datalog);
		return;
	}
	
	
	// Write header information
	logger_log(LOGGER_HEADERTEXT);
	logger_log("\n-- BEGIN DATA --\n");
	
	error_log_rawwrite(LOGGER_HEADERTEXT);
	error_log_rawwrite("\n-- BEGIN ERROR --\n");
	error_log_rawwrite("\nErrorNo,ErrorMsg,ErrorInfo,\r\n");
}	

void logger_log(char *buffer) 
{
	uint8_t len = strlen(buffer);
	if(fat_write_file(fd_datalog, (uint8_t*) buffer, len) != len)
	{
		// Error writing to file
		return;
	}
}

void error_log(uint8_t errNo, bool flashLED)
{
	char labelBuffer[32];
	labelBuffer[0] = 0x00;
	
	if(errNo <= MAX_ERRNO) 
	{
		strncpy_P(labelBuffer,(char*)pgm_read_word(&(errorMessageLookup[errNo])),32);
	}
	char errorLine[128];
	snprintf(errorLine, 128, "%lu, %u, %s,,\r\n", time_millis(), errNo, labelBuffer);
	error_log_rawwrite(errorLine);
	
	led_on(LED_ERROR);
	if(flashLED) 
	{
		led_errorcode(errNo);
	}	
}

void error_log_msg(uint8_t errNo, bool flashLED, char* infoText)
{
	char labelBuffer[32];
	labelBuffer[0] = 0x00;
	
	if(errNo <= MAX_ERRNO)
	{
		strncpy_P(labelBuffer,(char*)pgm_read_word(&(errorMessageLookup[errNo])),32);
	}
	char errorLine[256];
	snprintf(errorLine, 256, "%lu,%u,%s,%s,\r\n", time_millis(), errNo, labelBuffer, infoText);
	error_log_rawwrite(errorLine);
	
	led_on(LED_ERROR);
	if(flashLED)
	{
		led_errorcode(errNo);
	}
}

void info_log_msg(char* infoText)
{
	char errorLine[256];
	snprintf(errorLine, 256, "%lu,8,infotext,%s,\r\n", time_millis(), infoText);
	error_log_rawwrite(errorLine);
}


void error_log_rawwrite(char *buffer) 
{
	uint8_t len = strlen(buffer);
	if(fat_write_file(fd_errorlog, (uint8_t*) buffer, len) != len)
	{
		// Error writing to file
		return;
	}
}


void logger_closeLog() 
{
	fat_close_file(fd_datalog);
	fat_close_dir(dd);
	fat_close(fs);
	partition_close(partition);
}


// INTERNAL FUNCTIONS

// Opens a file so it can be read/written
struct fat_file_struct* open_file_in_dir(struct fat_fs_struct* fs, struct fat_dir_struct* dd, const char* name)
{
	struct fat_dir_entry_struct file_entry;
	if(!find_file_in_dir(fs, dd, name, &file_entry))
	return 0;

	return fat_open_file(fs, &file_entry);
}

// Searches for file in directory listing
uint8_t find_file_in_dir(struct fat_fs_struct* fs, struct fat_dir_struct* dd, const char* name, struct fat_dir_entry_struct* dir_entry)
{
	while(fat_read_dir(dd, dir_entry))
	{
		if(strcmp(dir_entry->long_name, name) == 0)
		{
			fat_reset_dir(dd);
			return 1;
		}
	}
	return 0;
}