Changeset - dc8e0a6ef3b7
[Not reviewed]
default
0 6 0
ethanzonca@CL-ENS241-08.cedarville.edu - 12 years ago 2013-04-12 15:47:19
ethanzonca@CL-ENS241-08.cedarville.edu
Commenting and syntax fixes
6 files changed with 63 insertions and 40 deletions:
0 comments (0 inline, 0 general)
master/master/lib/ini/ini.c
Show inline comments
 
/* inih -- simple .INI file parser
 
 
inih is released under the New BSD license (see LICENSE.txt). Go to the project
 
home page for more info:
 
 
http://code.google.com/p/inih/
 
 
/*
 
 * Master Firmware: INI Parse Backend
 
 *
 
 * Wireless Observational Modular Aerial Network
 
 * 
 
 * Ethan Zonca
 
 * Matthew Kanning
 
 * Kyle Ripperger
 
 * Matthew Kroening
 
 *
 
 * This library was modified to use SD card FAT read/write operations
 
 *
 
 * Original library:
 
 *
 
 *	 inih is released under the New BSD license (see LICENSE.txt). Go to the project
 
 *	 home page for more info:
 
 *	 http://code.google.com/p/inih/
 
 *
 
*/
 
 
#include <stdio.h>
 
#include <ctype.h>
 
#include <string.h>
 
 
#include "ini.h"
 
#include "../logger.h"
 
 
#if !INI_USE_STACK
 
#include <stdlib.h>
 
#endif
 
 
#define MAX_SECTION 50
 
#define MAX_NAME 50
 
 
 
/* Strip whitespace chars off end of given string, in place. Return s. */
 
static char* rstrip(char* s)
 
{
 
    char* p = s + strlen(s);
 
    while (p > s && isspace((unsigned char)(*--p)))
 
        *p = '\0';
 
    return s;
 
}
 
 
/* Return pointer to first non-whitespace char in given string. */
 
static char* lskip(const char* s)
 
{
 
    while (*s && isspace((unsigned char)(*s)))
 
        s++;
 
    return (char*)s;
 
}
 
 
/* Return pointer to first char c or ';' comment in given string, or pointer to
 
   null at end of string if neither found. ';' must be prefixed by a whitespace
 
   character to register as a comment. */
 
static char* find_char_or_comment(const char* s, char c)
 
{
 
    int was_whitespace = 0;
 
    while (*s && *s != c && !(was_whitespace && *s == ';')) {
 
        was_whitespace = isspace((unsigned char)(*s));
 
        s++;
 
    }
 
    return (char*)s;
 
}
 
 
/* Version of strncpy that ensures dest (size bytes) is null-terminated. */
 
static char* strncpy0(char* dest, const char* src, size_t size)
 
{
 
    strncpy(dest, src, size);
 
    dest[size - 1] = '\0';
 
    return dest;
 
}
 
 
/* See documentation in header file. */
 
int ini_parse_file(int (*handler)(void*, const char*, const char*,
 
                   const char*),
 
                   void* user)
 
{
 
	
 
    /* Uses a fair bit of stack (use heap instead if you need to) */
 
#if INI_USE_STACK
 
    char line[INI_MAX_LINE];
 
#else
 
    char* line;
 
#endif
 
    char section[MAX_SECTION] = "";
 
    char prev_name[MAX_NAME] = "";
 
 
    char* start;
 
    char* end;
 
    char* name;
 
    char* value;
 
    int lineno = 0;
 
    int error = 0;
 
 
#if !INI_USE_STACK
 
    line = (char*)malloc(INI_MAX_LINE);
 
    if (!line) {
 
        return -2;
 
    }
 
#endif
 
	
 
    /* Scan through file line by line */
 
    while (logger_config_fgets(line, INI_MAX_LINE) != NULL) {
 
        lineno++;
 
 
        start = line;
 
#if INI_ALLOW_BOM
 
        if (lineno == 1 && (unsigned char)start[0] == 0xEF &&
 
                           (unsigned char)start[1] == 0xBB &&
 
                           (unsigned char)start[2] == 0xBF) {
 
            start += 3;
 
        }
 
#endif
 
        start = lskip(rstrip(start));
 
 
        if (*start == ';' || *start == '#') {
 
            /* Per Python ConfigParser, allow '#' comments at start of line */
 
        }
 
#if INI_ALLOW_MULTILINE
 
        else if (*prev_name && *start && start > line) {
 
            /* Non-black line with leading whitespace, treat as continuation
 
               of previous name's value (as per Python ConfigParser). */
 
            if (!handler(user, section, prev_name, start) && !error)
 
                error = lineno;
 
        }
 
#endif
 
        else if (*start == '[') {
 
            /* A "[section]" line */
 
            end = find_char_or_comment(start + 1, ']');
 
            if (*end == ']') {
master/master/lib/ini/ini.h
Show inline comments
 
/* inih -- simple .INI file parser
 
 
inih is released under the New BSD license (see LICENSE.txt). Go to the project
 
home page for more info:
 
 
http://code.google.com/p/inih/
 
 
/*
 
 * Master Firmware: INI Parse Backend
 
 *
 
 * Wireless Observational Modular Aerial Network
 
 * 
 
 * Ethan Zonca
 
 * Matthew Kanning
 
 * Kyle Ripperger
 
 * Matthew Kroening
 
 *
 
 * This library was modified to use SD card FAT read/write operations
 
 *
 
 * Original library:
 
 *
 
 *	 inih is released under the New BSD license (see LICENSE.txt). Go to the project
 
 *	 home page for more info:
 
 *	 http://code.google.com/p/inih/
 
 *
 
*/
 
 
#ifndef __INI_H__
 
#define __INI_H__
 
 
/* Make this header file easier to include in C++ code */
 
#ifdef __cplusplus
 
extern "C" {
 
#endif
 
 
#include <stdio.h>
 
 
/* Parse given INI-style file. May have [section]s, name=value pairs
 
   (whitespace stripped), and comments starting with ';' (semicolon). Section
 
   is "" if name=value pair parsed before any section heading. name:value
 
   pairs are also supported as a concession to Python's ConfigParser.
 
 
   For each name=value pair parsed, call handler function with given user
 
   pointer as well as section, name, and value (data only valid for duration
 
   of handler call). Handler should return nonzero on success, zero on error.
 
 
   Returns 0 on success, line number of first error on parse error (doesn't
 
   stop on first error), -1 on file open error, or -2 on memory allocation
 
   error (only when INI_USE_STACK is zero).
 
*/
 
int ini_parse_file(int (*handler)(void*, const char*, const char*,
 
					const char*),
 
					void* user);
 
 
int ini_parse(int (*handler)(void*, const char*, const char*, const char*),
 
				void* user);
 
 
/* Nonzero to allow multi-line value parsing, in the style of Python's
 
   ConfigParser. If allowed, ini_parse() will call the handler with the same
 
   name for each subsequent line parsed. */
 
#ifndef INI_ALLOW_MULTILINE
 
#define INI_ALLOW_MULTILINE 1
 
#endif
 
 
/* Nonzero to allow a UTF-8 BOM sequence (0xEF 0xBB 0xBF) at the start of
 
   the file. See http://code.google.com/p/inih/issues/detail?id=21 */
 
#ifndef INI_ALLOW_BOM
 
#define INI_ALLOW_BOM 1
 
#endif
 
 
/* Nonzero to use stack, zero to use heap (malloc/free). */
 
#ifndef INI_USE_STACK
 
#define INI_USE_STACK 1
 
#endif
 
 
/* Maximum line length for any line in INI file. */
 
#ifndef INI_MAX_LINE
 
#define INI_MAX_LINE 25
 
#endif
 
 
#ifdef __cplusplus
 
}
 
#endif
 
 
#endif /* __INI_H__ */
master/master/lib/iniparse.c
Show inline comments
 
/*
 
 * Master Firmware: INI Parser
 
 *
 
 * Wireless Observational Modular Aerial Network
 
 * 
 
 * Ethan Zonca
 
 * Matthew Kanning
 
 * Kyle Ripperger
 
 * Matthew Kroening
 
 *
 
 */
 

	
 
#include "../config.h"
 
#include <stdbool.h>
 
#include <stdlib.h>
 
#include <string.h>
 
#include "iniparse.h"
 
#include "ini/ini.h"
 
#include "logger.h"
 
 
 
// Callback function for INI file parsing
 
static int handler(void* user, const char* section, const char* name, const char* value)
 
{
 
	
 
	configuration* pconfig = (configuration*)user;
 
 
	#define MATCH(s, n) strcmp(section, s) == 0 && strcmp(name, n) == 0
 
		
 
	// MATCH(section name, variable name)
 
	if (MATCH("general", "temp")) {
 
		pconfig->heater_threshold = atoi(value);
 
		
 
		
 
	} else if (MATCH("general", "reqrate")) {
 
		pconfig->datarequest_rate = strtol(value, NULL, 10);
 
		
 
		
 
	} else if (MATCH("blackout", "enable")) {
 
		pconfig->blackout_enable = strncmp(value, "false", 4);
 
		
 
		
 
	} else if (MATCH("blackout", "timeout")) {
 
		pconfig->blackout_timeout = strtol(value, NULL, 10);
 
		
 
		
 
	} else if (MATCH("buzzer", "failsafe")) {
 
		pconfig->buzzer_failsafe_duration = strtol(value, NULL, 10);
 
		
 
		
 
	} else if (MATCH("buzzer", "mintime")) {
 
		pconfig->buzzer_trigger_minduration = strtol(value, NULL, 10);
 
		
 
	} else if (MATCH("buzzer", "maxalt")) {
 
		pconfig->buzzer_trigger_maxaltitude = strtol(value, NULL, 10);
 
		
 
	} else if (MATCH("aprs", "call")) {
 
		strncpy(pconfig->s_callsign, value, 10);
 
		//pconfig->s_callsign = strdup(value);
 
		
 
		
 
	} else if (MATCH("aprs", "call_id")) {
 
		pconfig->s_callsign_id = atoi(value);
 
		
 
		
 
	} else if (MATCH("aprs", "period")) {
 
		pconfig->aprs_transmit_period = strtol(value, NULL, 10);
 
		
 
	} else {
 
		error_log_msg(ERROR_CONFIGPARSE,false,"bad entry");
 
		return 0;  /* unknown section/name, error */
 
	}
 
	
 
	
 
	return 1;
 
}
 

	
 
configuration config = {
 
// Initialize configuration structure pre-set to DEFINE'ed defaults
 
configuration config = 
 
{
 
	#ifdef BLACKOUT_ENABLE
 
	.blackout_enable = true,
 
	#else
 
	.blackout_enable = false,
 
	#endif
 
		
 
	.blackout_timeout = BLACKOUT_TIMEOUT,
 
	.heater_threshold = HEATER_THRESHOLD,
 
	.buzzer_failsafe_duration = BUZZER_FAILSAFE_DURATION,
 
	.buzzer_trigger_minduration = BUZZER_TRIGGER_MINDURATION,
 
	.buzzer_trigger_maxaltitude = BUZZER_TRIGGER_MAXALTITUDE,
 
	.datarequest_rate = DATAREQUEST_RATE,
 
	.s_callsign = S_CALLSIGN,
 
	.s_callsign_id = S_CALLSIGN_ID,
 
	.aprs_transmit_period = APRS_TRANSMIT_PERIOD
 
};
 

	
 
// Parse config file from SD card and set global configuration struct
 
void iniparse_getconfig()
 
{
 
	// Init configuration with default values from config.h
 
 
	if (ini_parse(handler, &config) < 0) {
 
		// ERROR: Make new error code here!
 
	if (ini_parse(handler, &config) < 0)
 
	{
 
		error_log(ERROR_CONFIGPARSE, false);
 
	}
 
 
	sysconfig = &config;
 
	
 
	// Print configuration to err
 
	// Print critical configuration options to CSV error log for reference
 
	error_log_rawwrite("\nConf:\n");
 
		
 
	char msg[50];
 
	snprintf(msg, 50,"reqrate: %lu\n",sysconfig->datarequest_rate);
 
	error_log_rawwrite(msg);
 
	snprintf(msg, 50,"call: %s\n",sysconfig->s_callsign);
 
	error_log_rawwrite(msg);
 
	snprintf(msg, 50,"callID: %u\n",sysconfig->s_callsign_id);
 
	error_log_rawwrite(msg);
 
	snprintf(msg, 50,"aprsperiod: %lu\n\n",sysconfig->aprs_transmit_period);
 
	error_log_rawwrite(msg);
 
	
 
	return;
 
}
 
\ No newline at end of file
master/master/lib/iniparse.h
Show inline comments
 
/*
 
 * Master Firmware: INI Parser
 
 *
 
 * Wireless Observational Modular Aerial Network
 
 * 
 
 * Ethan Zonca
 
 * Matthew Kanning
 
 * Kyle Ripperger
 
 * Matthew Kroening
 
 *
 
 */
 
 
 
#ifndef INIPARSE_H_
 
#define INIPARSE_H_
 
 
 
 
void iniparse_getconfig();
 
 
#endif /* INIPARSE_H_ */
 
\ No newline at end of file
master/master/lib/watchdog.c
Show inline comments
 
/*
 
 * Master Firmware: Watchdog Timer
 
 *
 
 * Wireless Observational Modular Aerial Network
 
 * 
 
 * Ethan Zonca
 
 * Matthew Kanning
 
 * Kyle Ripperger
 
 * Matthew Kroening
 
 *
 
 */
 
 
#include "../config.h"
 
#include <avr/io.h>
 
#include <avr/interrupt.h>
 
#include <avr/wdt.h>
 
#include <util/delay.h>
 
#include <avr/eeprom.h>
 
 
#include "looptime.h"
 
#include "led.h"
 
#include "logger.h"
 
 
//initialize watchdog
 
 
// Initialize watchdog timer
 
void watchdog_setup(void)
 
{
 
	cli();
 
	wdt_reset();
 
	// Set change enable bit, enable the WDT
 
	WDTCSR = (1<<WDCE)|(1<<WDE)| (1<<WDIE);
 
	// Start watchdog, 4 second timeout
 
	WDTCSR = (1<<WDE)|(1<<WDP3)|(1<<WDP0)|(1<<WDIE);
 
	sei();
 
}
 
 
// Check if a WDT reset occurred on the previous boot
 
void watchdog_checkreset(void)
 
{
 
	// Check if WDT reset occurred
 
	if( (MCUSR & (1<<WDRF)) > 0)
 
	{
 
		MCUSR &= ~(1<<WDRF);
 
		
 
		// Restore timer from EEPROM
 
		// Restore software program timer from EEPROM
 
		uint32_t oldtimer = 0;
 
		oldtimer = eeprom_read_dword((uint32_t*)WATCHDOG_PROGTIMER_EEPROM_ADDR);
 
		time_watchdogrestore(oldtimer);
 
		
 
		// Log error to SD card
 
		error_log_msg(ERROR_WATCHDOG,false,"Booting up after watchdog reset");
 
	}
 
}
 
 
// Store program timer to EEPROM before WDT reboot
 
ISR(WDT_vect) 
 
{
 
	// Store timer in EEPROM
 
	eeprom_write_dword((uint32_t*)WATCHDOG_PROGTIMER_EEPROM_ADDR, time_millis());
 
	// Store timer + WDT delay in EEPROM
 
	eeprom_write_dword((uint32_t*)WATCHDOG_PROGTIMER_EEPROM_ADDR, time_millis()+4000);
 
	
 
	// Trippy error LEDs while waiting 4 seconds for system reset
 
	// Flash all LEDs while waiting 4 seconds for system reset
 
	while(1)
 
	{
 
		led_on(LED_ACT0);
 
		led_on(LED_ACT1);
 
		led_on(LED_ACT2);
 
		led_on(LED_ACT3);
 
		led_on(LED_ERROR);
 
		led_on(LED_STATUS);
 
		led_on(LED_ACTIVITY);
 
		led_on(LED_SIDEBOARD);
 
		_delay_ms(50);
 
		led_off(LED_ACT0);
 
		led_off(LED_ACT1);
 
		led_off(LED_ACT2);
 
		led_off(LED_ACT3);
 
		led_off(LED_ERROR);
 
		led_off(LED_STATUS);
 
		led_off(LED_ACTIVITY);
 
		led_off(LED_SIDEBOARD);
 
		_delay_ms(50);
 
	}	
 
}
 
\ No newline at end of file
master/master/master.c
Show inline comments
 
/*
 
 * Master Firmware
 
 *
 
 * Wireless Observational Modular Aerial Network
 
 * 
 
 * Ethan Zonca
 
 * Matthew Kanning
 
 * Kyle Ripperger
 
 * Matthew Kroening
 
 *
 
 */
 

	
 

	
 
#include "config.h"
 

	
 
#include <avr/io.h>
 
#include <util/delay.h>
 
#include <avr/wdt.h>
 
#include <avr/interrupt.h>
 
#include <stdio.h>
 
#include <stdbool.h>
 
#include <string.h>
 

	
 
#include "lib/serial.h"
 
#include "lib/aprs.h"
 
#include "lib/afsk.h"
 
#include "lib/led.h"
 
#include "lib/logger.h"
 
#include "lib/watchdog.h"
 
#include "lib/gps.h"
 
#include "lib/i2c.h"
 
#include "lib/sensors.h"
 
#include "lib/heater.h"
 
#include "lib/looptime.h"
 
#include "lib/slavesensors.h"
 
#include "lib/serparser.h"
 
#include "lib/sensordata.h"
 
#include "lib/iniparse.h"
 

	
 
int main(void)
 
{
 
	// Initialize libraries
 
	time_setup();
 
	watchdog_setup(); // enables interrupts
 
	
 
	// Power debounce
 
	_delay_ms(1000);
 
	
 
	led_setup();
 
	gps_setup();
 
	serial0_setup();
 
	serial1_setup();
 
	i2c_init();
 
	sensordata_setup(); // must happen before slavesensors/logger/AFSK
 
	slavesensors_setup();
 
	sensors_setup();
 
	logger_setup();
 
	watchdog_checkreset();
 
	iniparse_getconfig();
 
	afsk_setup();
 
	serial0_sendString("Hello.\n\n");
 
	
 
	// Blocking ZigBee node discovery
 
	// ZigBee network discovery (blocking ~6s)
 
	slavesensors_network_scan();
 
	
 
	// Software timers	
 
	uint32_t lastAprsBroadcast = 0;
 
	uint32_t lastLog = 0;
 
	uint32_t lastLedCycle = 0;
 
	uint32_t lastDataReq = 0;
 
	uint32_t lastBuzz = 0;
 
	uint32_t lastBuzzOn = 0;
 
	
 
	bool buzz = false;
 
	
 
	// Result of last parser run
 
	int parseResult = PARSERESULT_NODATA;
 
	
 
	while(1)
 
    {
 
		// Periodic: LED execution indicator
 
		if(time_millis() - lastLedCycle > LEDCYCLE_RATE) 
 
		{
 
			led_power_toggle();
 
			led_spin();
 
			
 
			// Enable GPS serial interrupts if we aren't doing AFSK
 
			if(!afsk_busy())
 
				serial1_ion();
 
				
 
			lastLedCycle = time_millis();	
 
		}
 
		
 
		// Periodic: Logging
 
		if(time_millis() - lastLog > LOGGER_RATE) 
 
		{
 
			led_on(LED_CYCLE);
 
			
 
			heater_regulateTemp();
 
			
 
			// Turn on sideboard LED if we have a fix
 
			if(gps_hasfix()) 
 
			{
 
				led_on(LED_SIDEBOARD);
 
			}
 
			else 
 
			{
 
				led_off(LED_SIDEBOARD);
 
			}
 
			
 
			// Read board temperature and battery level
 
			sensors_readBoardTemp();
 
			sensors_readBatt();
 
		
 
			// Write CSV header and log data values
 
			sensordata_logvalues();			
 
			
 
			led_off(LED_CYCLE);
 
			lastLog = time_millis();
 
		}		
 
		
 
		// Periodic: Buzzer
 
		if(time_millis() - lastBuzz > BUZZER_RATE) {
 
		if(time_millis() - lastBuzz > BUZZER_RATE)
 
		{
 
			if(sensordata_isTouchdown())
 
			{
 
				led_on(LED_BUZZ);
 
				lastBuzzOn = time_millis();
 
				buzz = true;
 
			}			
 
			lastBuzz = time_millis();
 
		}
 
		 
 
		if(buzz && time_millis() - lastBuzzOn > BUZZER_DURATION) {
 
		if(buzz && time_millis() - lastBuzzOn > BUZZER_DURATION) 
 
		{
 
			led_off(LED_BUZZ);
 
			buzz = false;
 
		}
 
		
 
		// Periodic: Data Request
 
		if(time_millis() - lastDataReq > sysconfig->datarequest_rate)  
 
		{
 
			// Start getting values for next transmission
 
			if(slavesensors_isrequesting())
 
			{
 
				// This probably is a non-issue
 
				//error_log_msg(ERROR_FATAL, false, "Still requesting on following loop");
 
			}
 
			else
 
			{
 
				slavesensors_startprocess();
 
			}
 
			
 
			lastDataReq = time_millis();
 
		}
 
		
 
		
 
		// Periodic: APRS transmission
 
		if(time_millis() - lastAprsBroadcast > sysconfig->aprs_transmit_period) 
 
		{
 
			// Check for touchdown
 
			sensordata_checkTouchdown();
 
			
 
			// Ensure we aren't already transmitting
 
			while(afsk_busy());
 
			
 
			// Turn off interrupts and transmit APRS sentence
 
			serial1_ioff();
 
			aprs_send(); // non-blocking
 
			
 
			lastAprsBroadcast = time_millis();
 
		}			
 
		
 
		// Periodic: Blackout timer check
 
		bool black = false;
 
		if(sysconfig->blackout_enable && !black && time_millis() > sysconfig->blackout_timeout) 
 
		{
 
			// LED blackout
 
			led_blackout();
 
			black = true;
 
		}
 
		
 
		// Parse any serial data in the XBee software buffer
 
		parseResult = serparser_parse();
 
		slavesensors_process(parseResult);
 
		
 
		
 
		// Parse any NMEA messages in the GPS software buffer
 
		parse_gps_transmission();
 
		
 
		
 
		wdt_reset();
 
    }
 
}
 
\ No newline at end of file
0 comments (0 inline, 0 general)