Changeset - 48acfcb35ad3
[Not reviewed]
default
0 11 2
ethanzonca@CL-SEC241-08.cedarville.edu - 13 years ago 2012-11-27 21:36:13
ethanzonca@CL-SEC241-08.cedarville.edu
Added slave parser library, added infrastructure for requesting data from slave nodes
13 files changed with 209 insertions and 81 deletions:
0 comments (0 inline, 0 general)
master/master/config.h
Show inline comments
 
/*
 
 * config.h
 
 *
 
 * Created: 10/25/2012 3:28:22 PM
 
 *  Author: ethanzonca
 
 */ 
 
 
 
#ifndef CONFIG_H_
 
#define CONFIG_H_
 
 
#define F_CPU 11059200
 
#define MODULE_ID '1'
 
 
// --------------------------------------------------------------------------
 
// Slave Sensors config (slavesensors.c)
 
// --------------------------------------------------------------------------
 
 
#define SLAVE0_SENSORS BOARDTEMP
 
#define SLAVE1_SENSORS BOARDTEMP | HUMIDITY | TEMPERATURE | PRESSURE | AMBIENTLIGHT
 
#define SLAVE2_SENSORS BOARDTEMP | GEIGER
 
#define SLAVE3_SENSORS BOARDTEMP | CAMERA
 
#define SLAVE4_SENSORS NONE
 
#define SLAVE5_SENSORS NONE
 
#define SLAVE6_SENSORS NONE
 
#define SLAVE7_SENSORS NONE
 
 
// --------------------------------------------------------------------------
 
// USART config (serial.c)
 
// --------------------------------------------------------------------------
 
 
#define USART0_BAUDRATE 115200
 
#define USART1_BAUDRATE 115200
 
 
// --------------------------------------------------------------------------
 
// AX.25 config (ax25.c)
 
// --------------------------------------------------------------------------
 

	
 
// TX delay in milliseconds
 
#define TX_DELAY      300
 

	
 
// Maximum packet delay
 
#define MAX_PACKET_LEN 512  // bytes
 
 

	
 
// --------------------------------------------------------------------------
 
// APRS config (aprs.c)
 
// --------------------------------------------------------------------------
 

	
 
// Set your callsign and SSID here. Common values for the SSID are
 
// (from http://zlhams.wikidot.com/aprs-ssidguide):
 
//
 
// - Balloons:  11
 
// - Cars:       9
 
// - Home:       0
 
// - IGate:      5
 
#define S_CALLSIGN      "MYCALL"
 
#define S_CALLSIGN_ID   11
 

	
 
// Destination callsign: APRS (with SSID=0) is usually okay.
 
#define D_CALLSIGN      "APRS"
 
#define D_CALLSIGN_ID   0
 

	
 
// Digipeating paths:
 
// (read more about digipeating paths here: http://wa8lmf.net/DigiPaths/ )
 
// The recommended digi path for a balloon is WIDE2-1 or pathless. The default
 
// is pathless. Uncomment the following two lines for WIDE2-1 path:
 
#define DIGI_PATH1      "WIDE2"
 
#define DIGI_PATH1_TTL  1
 

	
 
// APRS comment: this goes in the comment portion of the APRS message. You
 
// might want to keep this short. The longer the packet, the more vulnerable
 
// it is to noise.
 
#define APRS_COMMENT    "Trackuino reminder: replace callsign with your own"
 
 
 
// Transmit the APRS sentence every X milliseconds
 
#define APRS_TRANSMIT_PERIOD 5000
 

	
 
// --------------------------------------------------------------------------
 
// Logger config (logger.c)
 
// --------------------------------------------------------------------------
 
 
#define LOGGER_ID_EEPROM_ADDR 0x10
 
 
// Written to the beginning of every log file
 
#define LOGGER_HEADERTEXT "HAB Control Master - 1.0\n"
 
 
// Log to SD card every X milliseconds
 
#define LOGGER_RATE 1000 
 
 
#endif /* CONFIG_H_ */
 
\ No newline at end of file
master/master/lib/aprs.c
Show inline comments
 
/*
 
 * aprs.c
 
 *
 
 * Created: 11/8/2012 3:40:57 PM
 
 *  Author: ethanzonca
 
 */ 
 
 
#include "../config.h"
 
#include "aprs.h"
 
#include "ax25.h"
 
#include <stdio.h>
 

	
 
const char *gps_aprs_lat = "somelatitudesomelatitudesomelatitudesomelatitudesomelatitudesomelatitude";
 
const char *gps_aprs_lon = "somelongitudesomelongitudesomelongitudesomelongitudesomelongitudesomelongitude";
 
const char *gps_time = "sometimedatasometimedatasometimedatasometimedatasometimedatasometimedata";
 
const char *gps_aprs_lat = "omgmylatitude";
 
const char *gps_aprs_lon = "omgmylongitude";
 
const char *gps_time = "omgmygpstime";
 
float gps_altitude = 123.5;
 
int gps_course = 5;
 
int gps_speed = 13;
 

	
 
float meters_to_feet(float m)
 
{
 
  // 10000 ft = 3048 m
 
  return m / 0.3048;
 
}
 

	
 
void aprs_send()
 
{
 
  char temp[12];                   // Temperature (int/ext)
 
  const struct s_address addresses[] = { 
 
    {D_CALLSIGN, D_CALLSIGN_ID},  // Destination callsign
 
    {S_CALLSIGN, S_CALLSIGN_ID},  // Source callsign (-11 = balloon, -9 = car)
 
#ifdef DIGI_PATH1
 
    {DIGI_PATH1, DIGI_PATH1_TTL}, // Digi1 (first digi in the chain)
 
#endif
 
#ifdef DIGI_PATH2
 
    {DIGI_PATH2, DIGI_PATH2_TTL}, // Digi2 (second digi in the chain)
 
#endif
 
  };
 

	
 
	// emz: modified this to get the size of the first address rather than the size of the struct itself, which fails
 
  ax25_send_header(addresses, sizeof(addresses)/sizeof(addresses[0]));
 
  ax25_send_byte('/');                // Report w/ timestamp, no APRS messaging. $ = NMEA raw data
 
  // ax25_send_string("021709z");     // 021709z = 2nd day of the month, 17:09 zulu (UTC/GMT)
 
  ax25_send_string(gps_time);         // 170915 = 17h:09m:15s zulu (not allowed in Status Reports)
 
  ax25_send_byte('h');
 
  ax25_send_string(gps_aprs_lat);     // Lat: 38deg and 22.20 min (.20 are NOT seconds, but 1/100th of minutes)
 
  ax25_send_byte('/');                // Symbol table
 
  ax25_send_string(gps_aprs_lon);     // Lon: 000deg and 25.80 min
 
  ax25_send_byte('O');                // Symbol: O=balloon, -=QTH
 
  snprintf(temp, 4, "%03d", (int)(gps_course + 0.5)); 
 
  ax25_send_string(temp);             // Course (degrees)
 
  ax25_send_byte('/');                // and
 
  snprintf(temp, 4, "%03d", (int)(gps_speed + 0.5));
 
  ax25_send_string(temp);             // speed (knots)
 
  ax25_send_string("/A=");            // Altitude (feet). Goes anywhere in the comment area
 
  snprintf(temp, 7, "%06ld", (long)(meters_to_feet(gps_altitude) + 0.5));
 
  ax25_send_string(temp);
 
  ax25_send_string("/Ti=");
 
  snprintf(temp, 6, "%d", 122);//sensors_int_lm60()); -- PUT SENSOR DATA HERE
 
  ax25_send_string(temp);
 
  ax25_send_string("/Te=");
 
  snprintf(temp, 6, "%d", 123);//sensors_ext_lm60());
 
  ax25_send_string(temp);
 
  ax25_send_string("/V=");
 
  snprintf(temp, 6, "%d", 123);//sensors_vin());
 
  ax25_send_string(temp);
 
  ax25_send_byte(' ');
 
  ax25_send_string(APRS_COMMENT);     // Comment
 
  ax25_send_footer();
 

	
 
  ax25_flush_frame();                 // Tell the modem to go
 
}
master/master/lib/logger.c
Show inline comments
 
/*
 
 * CFile1.c
 
 *
 
 * Created: 11/7/2012 8:05:44 PM
 
 *  Author: mkanning
 
 */ 
 
 
#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 "sd/fat.h"
 
#include "sd/fat_config.h"
 
#include "sd/partition.h"
 
#include "sd/sd_raw.h"
 
#include "sd/sd_raw_config.h"
 
#include "logger.h"
 
 
 
/* 
 
	//config edits
 
  * By changing the MCU* variables in the Makefile, you can use other Atmel
 
  * microcontrollers or different clock speeds. You might also want to change
 
  * the configuration defines in the files fat_config.h, partition_config.h,
 
  * sd_raw_config.h and sd-reader_config.h. For example, you could disable
 
  * write support completely if you only need read support.
 
 */
 
 
 
struct partition_struct* partition;
 
struct fat_fs_struct* fs;
 
struct fat_dir_entry_struct directory;
 
struct fat_dir_struct* dd;
 
struct fat_file_struct* fd;
 
 
void logger_setup()
 
{
 
 
	if(!sd_raw_init())
 
	{
 
		// initialization failed
 
		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
 
		// If the partition did not open, assume the storage device is a "superfloppy", i.e. has no MBR.
 
		partition = partition_open(sd_raw_read, sd_raw_read_interval, sd_raw_write, sd_raw_write_interval, -1);
 
		if(!partition)
 
		{
 
			// opening partition failed
 
			return;
 
		}
 
	}
 
	
 
	
 
	// Open FAT filesystem
 
	fs = fat_open(partition);
 
	if(!fs)
 
	{
 
		// opening filesystem failed
 
		return;
 
	}
 
	
 
	// Open directory
 
	fat_get_dir_entry_of_path(fs, "/", &directory);
 

	
 
	dd = fat_open_dir(fs, &directory);
 
	if(!dd)
 
	{
 
		// opening root directory failed
 
		_delay_ms(10);
 
		return;
 
	}
 
	
 
		
 
	// Create new log file
 
	uint8_t logid = eeprom_read_byte(LOGGER_ID_EEPROM_ADDR);
 
	char filename[48];
 
	
 
	// we pre-increment logid here because it starts at 255, then wraps to 0
 
	sprintf(filename, "data%d.csv",++logid);
 
	
 
	// TODO: Catch errors here
 
	fat_create_file(dd, filename, &directory);
 
		
 
	eeprom_update_byte(LOGGER_ID_EEPROM_ADDR, logid);
 

	
 
	// Search for file in current directory and open it
 
	fd = open_file_in_dir(fs, dd, filename);
 
	if(!fd)
 
	{
 
		_delay_ms(10);
 
		return;
 
	}
 
	
 
	// Seek to beginning of file
 
	// TODO: Is this needed?
 
	int32_t offset = 0; 
 
	if(!fat_seek_file(fd, &offset, FAT_SEEK_SET))
 
	{
 
		// Error seeking to file
 
		_delay_ms(10);
 
		fat_close_file(fd);
 
		return;
 
	}
 
		
 
	// Write header information
 
	logger_log(LOGGER_HEADERTEXT);
 
	logger_log("\n-- BEGIN DATA --\n");
 
	logger_log("C1, C2, C3, C4, C5, C6\n");
 
	
 
}	
 
 
void logger_log(char *buffer) {
 
	uint8_t len = strlen(buffer);
 
	if(fat_write_file(fd, (uint8_t*) buffer, len) != len)
 
	{
 
		// Error writing to file
 
		return;
 
	}
 
}
 
 
void logger_closeLog() {
 
	fat_close_file(fd);
 
	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;
 
}
master/master/lib/looptime.c
Show inline comments
 
/*
 
 * looptime.c
 
 *
 
 * Created: 11/19/2012 8:56:42 PM
 
 *  Author: ethanzonca
 
 */ 
 
 
#include "../config.h"
 
#include <avr/io.h>
 
#include <avr/interrupt.h>
 
#include <avr/delay.h>
 
extern volatile uint32_t millis = 0; // Milliseconds since initialization
 
#include <util/delay.h>
 
volatile uint32_t millis = 0; // Milliseconds since initialization
 

	
 

	
 

	
 
void time_setup() {
 
	DDRA = 0xff;
 
	
 
	// Generic microcontroller config options
 
	OCR0A = 173; // Approx 172.7969 ticks per ms with 64 prescaler
 
	
 
	TCCR0A |= (1 << WGM01) | (1 << WGM00); // Count until OCR0A, then overflow (wgm02 in the next line specifies this as well)
 
	TCCR0B |= (1 << CS01) | (1 << CS00) | (1 << WGM02); // clock div by 64
 
	TIFR0 |= ( 1 << TOV0 ); // clear pending interrupts
 
	TIMSK0 |= (1 << TOIE0); // enable overflow interrupt
 
}
 

	
 

	
 
ISR(TIMER0_OVF_vect) {
 
	millis = millis + 1;
 
}
 

	
 
uint32_t time_millis() {
 
	return millis; // meh accuracy, but that's OK
 
}
master/master/lib/sd/sd_raw.c
Show inline comments
 

	
 
/*
 
 * Copyright (c) 2006-2012 by Roland Riegel <feedback@roland-riegel.de>
 
 *
 
 * This file is free software; you can redistribute it and/or modify
 
 * it under the terms of either the GNU General Public License version 2
 
 * or the GNU Lesser General Public License version 2.1, both as
 
 * published by the Free Software Foundation.
 
 */
 

	
 
#include <string.h>
 
#include <avr/io.h>
 
#include "sd_raw.h"
 
#include "sd_raw_config.h"
 

	
 
/**
 
 * \addtogroup sd_raw MMC/SD/SDHC card raw access
 
 *
 
 * This module implements read and write access to MMC, SD
 
 * and SDHC cards. It serves as a low-level driver for the
 
 * higher level modules such as partition and file system
 
 * access.
 
 *
 
 * @{
 
 */
 
/**
 
 * \file
 
 * MMC/SD/SDHC raw access implementation (license: GPLv2 or LGPLv2.1)
 
 *
 
 * \author Roland Riegel
 
 */
 

	
 
/**
 
 * \addtogroup sd_raw_config MMC/SD configuration
 
 * Preprocessor defines to configure the MMC/SD support.
 
 */
 

	
 
/**
 
 * @}
 
 */
 

	
 
/* commands available in SPI mode */
 

	
 
/* CMD0: response R1 */
 
#define CMD_GO_IDLE_STATE 0x00
 
/* CMD1: response R1 */
 
#define CMD_SEND_OP_COND 0x01
 
/* CMD8: response R7 */
 
#define CMD_SEND_IF_COND 0x08
 
/* CMD9: response R1 */
 
#define CMD_SEND_CSD 0x09
 
/* CMD10: response R1 */
 
#define CMD_SEND_CID 0x0a
 
/* CMD12: response R1 */
 
#define CMD_STOP_TRANSMISSION 0x0c
 
/* CMD13: response R2 */
 
#define CMD_SEND_STATUS 0x0d
 
/* CMD16: arg0[31:0]: block length, response R1 */
 
#define CMD_SET_BLOCKLEN 0x10
 
/* CMD17: arg0[31:0]: data address, response R1 */
 
#define CMD_READ_SINGLE_BLOCK 0x11
 
/* CMD18: arg0[31:0]: data address, response R1 */
 
#define CMD_READ_MULTIPLE_BLOCK 0x12
 
/* CMD24: arg0[31:0]: data address, response R1 */
 
#define CMD_WRITE_SINGLE_BLOCK 0x18
 
/* CMD25: arg0[31:0]: data address, response R1 */
 
#define CMD_WRITE_MULTIPLE_BLOCK 0x19
 
/* CMD27: response R1 */
 
#define CMD_PROGRAM_CSD 0x1b
 
/* CMD28: arg0[31:0]: data address, response R1b */
 
#define CMD_SET_WRITE_PROT 0x1c
 
/* CMD29: arg0[31:0]: data address, response R1b */
 
#define CMD_CLR_WRITE_PROT 0x1d
 
/* CMD30: arg0[31:0]: write protect data address, response R1 */
 
#define CMD_SEND_WRITE_PROT 0x1e
 
/* CMD32: arg0[31:0]: data address, response R1 */
 
#define CMD_TAG_SECTOR_START 0x20
 
/* CMD33: arg0[31:0]: data address, response R1 */
 
#define CMD_TAG_SECTOR_END 0x21
 
/* CMD34: arg0[31:0]: data address, response R1 */
 
#define CMD_UNTAG_SECTOR 0x22
 
/* CMD35: arg0[31:0]: data address, response R1 */
 
#define CMD_TAG_ERASE_GROUP_START 0x23
 
/* CMD36: arg0[31:0]: data address, response R1 */
 
#define CMD_TAG_ERASE_GROUP_END 0x24
 
/* CMD37: arg0[31:0]: data address, response R1 */
 
#define CMD_UNTAG_ERASE_GROUP 0x25
 
/* CMD38: arg0[31:0]: stuff bits, response R1b */
 
#define CMD_ERASE 0x26
 
/* ACMD41: arg0[31:0]: OCR contents, response R1 */
 
#define CMD_SD_SEND_OP_COND 0x29
 
/* CMD42: arg0[31:0]: stuff bits, response R1b */
 
#define CMD_LOCK_UNLOCK 0x2a
 
/* CMD55: arg0[31:0]: stuff bits, response R1 */
 
#define CMD_APP 0x37
 
/* CMD58: arg0[31:0]: stuff bits, response R3 */
 
#define CMD_READ_OCR 0x3a
 
/* CMD59: arg0[31:1]: stuff bits, arg0[0:0]: crc option, response R1 */
 
#define CMD_CRC_ON_OFF 0x3b
 

	
 
/* command responses */
 
/* R1: size 1 byte */
 
#define R1_IDLE_STATE 0
 
#define R1_ERASE_RESET 1
 
#define R1_ILL_COMMAND 2
 
#define R1_COM_CRC_ERR 3
 
#define R1_ERASE_SEQ_ERR 4
 
#define R1_ADDR_ERR 5
 
#define R1_PARAM_ERR 6
 
/* R1b: equals R1, additional busy bytes */
 
/* R2: size 2 bytes */
 
#define R2_CARD_LOCKED 0
 
#define R2_WP_ERASE_SKIP 1
 
#define R2_ERR 2
 
#define R2_CARD_ERR 3
 
#define R2_CARD_ECC_FAIL 4
 
#define R2_WP_VIOLATION 5
 
#define R2_INVAL_ERASE 6
 
#define R2_OUT_OF_RANGE 7
 
#define R2_CSD_OVERWRITE 7
 
#define R2_IDLE_STATE (R1_IDLE_STATE + 8)
 
#define R2_ERASE_RESET (R1_ERASE_RESET + 8)
 
#define R2_ILL_COMMAND (R1_ILL_COMMAND + 8)
 
#define R2_COM_CRC_ERR (R1_COM_CRC_ERR + 8)
 
#define R2_ERASE_SEQ_ERR (R1_ERASE_SEQ_ERR + 8)
 
#define R2_ADDR_ERR (R1_ADDR_ERR + 8)
 
#define R2_PARAM_ERR (R1_PARAM_ERR + 8)
 
/* R3: size 5 bytes */
 
#define R3_OCR_MASK (0xffffffffUL)
 
#define R3_IDLE_STATE (R1_IDLE_STATE + 32)
 
#define R3_ERASE_RESET (R1_ERASE_RESET + 32)
 
#define R3_ILL_COMMAND (R1_ILL_COMMAND + 32)
 
#define R3_COM_CRC_ERR (R1_COM_CRC_ERR + 32)
 
#define R3_ERASE_SEQ_ERR (R1_ERASE_SEQ_ERR + 32)
 
#define R3_ADDR_ERR (R1_ADDR_ERR + 32)
 
#define R3_PARAM_ERR (R1_PARAM_ERR + 32)
 
/* Data Response: size 1 byte */
 
#define DR_STATUS_MASK 0x0e
 
#define DR_STATUS_ACCEPTED 0x05
 
#define DR_STATUS_CRC_ERR 0x0a
 
#define DR_STATUS_WRITE_ERR 0x0c
 

	
 
/* status bits for card types */
 
#define SD_RAW_SPEC_1 0
 
#define SD_RAW_SPEC_2 1
 
#define SD_RAW_SPEC_SDHC 2
 

	
 
#if !SD_RAW_SAVE_RAM
 
/* static data buffer for acceleration */
 
static uint8_t raw_block[512];
 
/* offset where the data within raw_block lies on the card */
 
static offset_t raw_block_address;
 
#if SD_RAW_WRITE_BUFFERING
 
/* flag to remember if raw_block was written to the card */
 
static uint8_t raw_block_written;
 
#endif
 
#endif
 

	
 
/* card type state */
 
static uint8_t sd_raw_card_type;
 

	
 
/* private helper functions */
 
static void sd_raw_send_byte(uint8_t b);
 
static uint8_t sd_raw_rec_byte();
 
static uint8_t sd_raw_send_command(uint8_t command, uint32_t arg);
 

	
 
/**
 
 * \ingroup sd_raw
 
 * Initializes memory card communication.
 
 *
 
 * \returns 0 on failure, 1 on success.
 
 */
 
uint8_t sd_raw_init()
 
{
 
    /* enable inputs for reading card status */
 
    configure_pin_available();
 
    configure_pin_locked();
 

	
 
    /* enable outputs for MOSI, SCK, SS, input for MISO */
 
    configure_pin_mosi();
 
    configure_pin_sck();
 
    configure_pin_ss();
 
    configure_pin_miso();
 

	
 
    unselect_card();
 
	
 
    // initialize SPI with lowest frequency; max. 400kHz during identification mode of card
 
    SPCR0 = (0 << SPIE0) | // SPI Interrupt Enable 
 
            (1 << SPE0)  | // SPI Enable 
 
            (0 << DORD0) | // Data Order: MSB first 
 
            (1 << MSTR0) | // Master mode 
 
            (0 << CPOL0) | // Clock Polarity: SCK low when idle 
 
            (0 << CPHA0) | // Clock Phase: sample on rising SCK edge 
 
            (1 << SPR10);   // Clock Frequency: f_OSC / 128 
 
            //(1 << SPR00); // commentnig this out means /64, which gives over 100khz as required
 
            (1 << SPR10);   // Clock Frequency: f_OSC / 64 which gives over 100khz required minimum clock
 
    SPSR0 &= ~(1 << SPI2X0); // No doubled clock frequency 
 

	
 
/*
 
	while(1) {
 
		SPDR0 = 'a';					//Load byte to Data register
 
		while(!(SPSR0 & (1<<SPIF0))); 	// Wait for transmission complete
 
	}
 
*/
 

	
 

	
 
    /* initialization procedure */
 
    sd_raw_card_type = 0;
 
    
 
    if(!sd_raw_available())
 
        return 0;
 

	
 
    /* card needs 74 cycles minimum to start up */
 
    for(uint8_t i = 0; i < 10; ++i)
 
    {
 
        /* wait 8 clock cycles */
 
        sd_raw_rec_byte();
 
    }
 

	
 
    /* address card */
 
    select_card();
 

	
 
    /* reset card */
 
    uint8_t response;
 
    for(uint16_t i = 0; ; ++i)
 
    {
 
        response = sd_raw_send_command(CMD_GO_IDLE_STATE, 0);
 
        if(response == (1 << R1_IDLE_STATE))
 
            break;
 

	
 
        if(i == 0x1ff)
 
        {
 
            unselect_card();
 
            return 0;
 
        }
 
    }
 

	
 
#if SD_RAW_SDHC
 
    /* check for version of SD card specification */
 
    response = sd_raw_send_command(CMD_SEND_IF_COND, 0x100 /* 2.7V - 3.6V */ | 0xaa /* test pattern */);
 
    if((response & (1 << R1_ILL_COMMAND)) == 0)
 
    {
 
        sd_raw_rec_byte();
 
        sd_raw_rec_byte();
 
        if((sd_raw_rec_byte() & 0x01) == 0)
 
            return 0; /* card operation voltage range doesn't match */
 
        if(sd_raw_rec_byte() != 0xaa)
 
            return 0; /* wrong test pattern */
 

	
 
        /* card conforms to SD 2 card specification */
 
        sd_raw_card_type |= (1 << SD_RAW_SPEC_2);
 
    }
 
    else
 
#endif
 
    {
 
        /* determine SD/MMC card type */
 
        sd_raw_send_command(CMD_APP, 0);
 
        response = sd_raw_send_command(CMD_SD_SEND_OP_COND, 0);
 
        if((response & (1 << R1_ILL_COMMAND)) == 0)
 
        {
 
            /* card conforms to SD 1 card specification */
 
            sd_raw_card_type |= (1 << SD_RAW_SPEC_1);
 
        }
 
        else
 
        {
 
            /* MMC card */
 
        }
 
    }
 

	
 
    /* wait for card to get ready */
 
    for(uint16_t i = 0; ; ++i)
 
    {
 
        if(sd_raw_card_type & ((1 << SD_RAW_SPEC_1) | (1 << SD_RAW_SPEC_2)))
 
        {
 
            uint32_t arg = 0;
 
#if SD_RAW_SDHC
 
            if(sd_raw_card_type & (1 << SD_RAW_SPEC_2))
 
                arg = 0x40000000;
 
#endif
 
            sd_raw_send_command(CMD_APP, 0);
 
            response = sd_raw_send_command(CMD_SD_SEND_OP_COND, arg);
 
        }
 
        else
 
        {
 
            response = sd_raw_send_command(CMD_SEND_OP_COND, 0);
 
        }
 

	
 
        if((response & (1 << R1_IDLE_STATE)) == 0)
 
            break;
 

	
 
        if(i == 0x7fff)
 
        {
 
            unselect_card();
 
            return 0;
 
        }
 
    }
 

	
 
#if SD_RAW_SDHC
 
    if(sd_raw_card_type & (1 << SD_RAW_SPEC_2))
 
    {
 
        if(sd_raw_send_command(CMD_READ_OCR, 0))
 
        {
 
            unselect_card();
 
            return 0;
 
        }
 

	
 
        if(sd_raw_rec_byte() & 0x40)
 
            sd_raw_card_type |= (1 << SD_RAW_SPEC_SDHC);
 

	
 
        sd_raw_rec_byte();
 
        sd_raw_rec_byte();
 
        sd_raw_rec_byte();
 
    }
 
#endif
 

	
 
    /* set block size to 512 bytes */
 
    if(sd_raw_send_command(CMD_SET_BLOCKLEN, 512))
 
    {
 
        unselect_card();
 
        return 0;
 
    }
 

	
 
    /* deaddress card */
 
    unselect_card();
 

	
 
    /* switch to highest SPI frequency possible */
 
    SPCR0 &= ~((1 << SPR10) | (1 << SPR00)); /* Clock Frequency: f_OSC / 4 */
 
    SPSR0 |= (1 << SPI2X0); /* Doubled Clock Frequency: f_OSC / 2 */
 

	
 
#if !SD_RAW_SAVE_RAM
 
    /* the first block is likely to be accessed first, so precache it here */
 
    raw_block_address = (offset_t) -1;
 
#if SD_RAW_WRITE_BUFFERING
 
    raw_block_written = 1;
 
#endif
 
    if(!sd_raw_read(0, raw_block, sizeof(raw_block)))
 
        return 0;
 
#endif
 

	
 
    return 1;
 
}
 

	
 
/**
 
 * \ingroup sd_raw
 
 * Checks wether a memory card is located in the slot.
 
 *
 
 * \returns 1 if the card is available, 0 if it is not.
 
 */
 
uint8_t sd_raw_available()
 
{
 
	int i;
 
	return 1; // !!TODO: OH GOSH CHANGE ME
 
    return get_pin_available() == 0x00;
 
}
 

	
 
/**
 
 * \ingroup sd_raw
 
 * Checks whether the memory card is locked for write access.
 
 *
 
 * \returns 1 if the card is locked, 0 if it is not.
 
 */
 
uint8_t sd_raw_locked()
 
{
 
	int i;
 
	// !!TODO oh gosh change me
 
	return 0;
 
    return get_pin_locked() == 0x00;
 
}
 

	
 
/**
 
 * \ingroup sd_raw
 
 * Sends a raw byte to the memory card.
 
 *
 
 * \param[in] b The byte to sent.
 
 * \see sd_raw_rec_byte
 
 */
 
void sd_raw_send_byte(uint8_t b)
 
{
 
    SPDR0 = b;
 
    /* wait for byte to be shifted out */
 
    while(!(SPSR0 & (1 << SPIF0)));
 
    SPSR0 &= ~(1 << SPIF0);
 
}
 

	
 
/**
 
 * \ingroup sd_raw
 
 * Receives a raw byte from the memory card.
 
 *
 
 * \returns The byte which should be read.
 
 * \see sd_raw_send_byte
 
 */
 
uint8_t sd_raw_rec_byte()
 
{
 
    /* send dummy data for receiving some */
 

	
 
    SPDR0 = 0xff;
 
    while(!(SPSR0 & (1 << SPIF0)));
 
    SPSR0 &= ~(1 << SPIF0);
 

	
 
    return SPDR0;
 
}
 

	
 
/**
 
 * \ingroup sd_raw
 
 * Send a command to the memory card which responses with a R1 response (and possibly others).
 
 *
 
 * \param[in] command The command to send.
 
 * \param[in] arg The argument for command.
 
 * \returns The command answer.
 
 */
 
uint8_t sd_raw_send_command(uint8_t command, uint32_t arg)
 
{
 
    uint8_t response;
 

	
 
    /* wait some clock cycles */
 
    sd_raw_rec_byte();
 

	
 
    /* send command via SPI */
 
    sd_raw_send_byte(0x40 | command);
 
    sd_raw_send_byte((arg >> 24) & 0xff);
 
    sd_raw_send_byte((arg >> 16) & 0xff);
 
    sd_raw_send_byte((arg >> 8) & 0xff);
 
    sd_raw_send_byte((arg >> 0) & 0xff);
 
    switch(command)
 
    {
 
        case CMD_GO_IDLE_STATE:
 
           sd_raw_send_byte(0x95);
 
           break;
 
        case CMD_SEND_IF_COND:
 
           sd_raw_send_byte(0x87);
 
           break;
 
        default:
 
           sd_raw_send_byte(0xff);
 
           break;
 
    }
 
    
 
    /* receive response */
 
    for(uint8_t i = 0; i < 10; ++i)
 
    {
 
        response = sd_raw_rec_byte();
 
        if(response != 0xff)
 
            break;
 
    }
 

	
 
    return response;
 
}
 

	
 
/**
 
 * \ingroup sd_raw
 
 * Reads raw data from the card.
 
 *
 
 * \param[in] offset The offset from which to read.
 
 * \param[out] buffer The buffer into which to write the data.
 
 * \param[in] length The number of bytes to read.
 
 * \returns 0 on failure, 1 on success.
 
 * \see sd_raw_read_interval, sd_raw_write, sd_raw_write_interval
 
 */
 
uint8_t sd_raw_read(offset_t offset, uint8_t* buffer, uintptr_t length)
 
{
 
    offset_t block_address;
 
    uint16_t block_offset;
 
    uint16_t read_length;
 
    while(length > 0)
 
    {
 
        /* determine byte count to read at once */
 
        block_offset = offset & 0x01ff;
 
        block_address = offset - block_offset;
 
        read_length = 512 - block_offset; /* read up to block border */
 
        if(read_length > length)
 
            read_length = length;
 
        
 
#if !SD_RAW_SAVE_RAM
 
        /* check if the requested data is cached */
 
        if(block_address != raw_block_address)
 
#endif
 
        {
 
#if SD_RAW_WRITE_BUFFERING
 
            if(!sd_raw_sync())
 
                return 0;
 
#endif
 

	
 
            /* address card */
 
            select_card();
 

	
 
            /* send single block request */
 
#if SD_RAW_SDHC
 
            if(sd_raw_send_command(CMD_READ_SINGLE_BLOCK, (sd_raw_card_type & (1 << SD_RAW_SPEC_SDHC) ? block_address / 512 : block_address)))
 
#else
 
            if(sd_raw_send_command(CMD_READ_SINGLE_BLOCK, block_address))
 
#endif
 
            {
 
                unselect_card();
 
                return 0;
 
            }
 

	
 
            /* wait for data block (start byte 0xfe) */
 
            while(sd_raw_rec_byte() != 0xfe);
 

	
 
#if SD_RAW_SAVE_RAM
 
            /* read byte block */
 
            uint16_t read_to = block_offset + read_length;
 
            for(uint16_t i = 0; i < 512; ++i)
 
            {
 
                uint8_t b = sd_raw_rec_byte();
 
                if(i >= block_offset && i < read_to)
 
                    *buffer++ = b;
 
            }
 
#else
 
            /* read byte block */
 
            uint8_t* cache = raw_block;
 
            for(uint16_t i = 0; i < 512; ++i)
 
                *cache++ = sd_raw_rec_byte();
 
            raw_block_address = block_address;
 

	
 
            memcpy(buffer, raw_block + block_offset, read_length);
 
            buffer += read_length;
 
#endif
 
            
 
            /* read crc16 */
 
            sd_raw_rec_byte();
 
            sd_raw_rec_byte();
 
            
 
            /* deaddress card */
 
            unselect_card();
 

	
 
            /* let card some time to finish */
 
            sd_raw_rec_byte();
 
        }
 
#if !SD_RAW_SAVE_RAM
 
        else
 
        {
 
            /* use cached data */
 
            memcpy(buffer, raw_block + block_offset, read_length);
 
            buffer += read_length;
 
        }
 
#endif
 

	
 
        length -= read_length;
 
        offset += read_length;
 
    }
 

	
 
    return 1;
 
}
 

	
 
/**
 
 * \ingroup sd_raw
 
 * Continuously reads units of \c interval bytes and calls a callback function.
 
 *
 
 * This function starts reading at the specified offset. Every \c interval bytes,
 
 * it calls the callback function with the associated data buffer.
 
 *
 
 * By returning zero, the callback may stop reading.
 
 *
 
 * \note Within the callback function, you can not start another read or
 
 *       write operation.
 
 * \note This function only works if the following conditions are met:
 
 *       - (offset - (offset % 512)) % interval == 0
 
 *       - length % interval == 0
 
 *
 
 * \param[in] offset Offset from which to start reading.
 
 * \param[in] buffer Pointer to a buffer which is at least interval bytes in size.
 
 * \param[in] interval Number of bytes to read before calling the callback function.
 
 * \param[in] length Number of bytes to read altogether.
 
 * \param[in] callback The function to call every interval bytes.
 
 * \param[in] p An opaque pointer directly passed to the callback function.
 
 * \returns 0 on failure, 1 on success
 
 * \see sd_raw_write_interval, sd_raw_read, sd_raw_write
 
 */
 
uint8_t sd_raw_read_interval(offset_t offset, uint8_t* buffer, uintptr_t interval, uintptr_t length, sd_raw_read_interval_handler_t callback, void* p)
 
{
 
    if(!buffer || interval == 0 || length < interval || !callback)
 
        return 0;
 

	
 
#if !SD_RAW_SAVE_RAM
 
    while(length >= interval)
 
    {
 
        /* as reading is now buffered, we directly
 
         * hand over the request to sd_raw_read()
 
         */
 
        if(!sd_raw_read(offset, buffer, interval))
 
            return 0;
 
        if(!callback(buffer, offset, p))
 
            break;
 
        offset += interval;
 
        length -= interval;
 
    }
 

	
 
    return 1;
 
#else
 
    /* address card */
 
    select_card();
 

	
 
    uint16_t block_offset;
 
    uint16_t read_length;
 
    uint8_t* buffer_cur;
 
    uint8_t finished = 0;
 
    do
 
    {
 
        /* determine byte count to read at once */
 
        block_offset = offset & 0x01ff;
 
        read_length = 512 - block_offset;
 
        
 
        /* send single block request */
 
#if SD_RAW_SDHC
 
        if(sd_raw_send_command(CMD_READ_SINGLE_BLOCK, (sd_raw_card_type & (1 << SD_RAW_SPEC_SDHC) ? offset / 512 : offset - block_offset)))
 
#else
 
        if(sd_raw_send_command(CMD_READ_SINGLE_BLOCK, offset - block_offset))
 
#endif
 
        {
 
            unselect_card();
 
            return 0;
 
        }
 

	
 
        /* wait for data block (start byte 0xfe) */
 
        while(sd_raw_rec_byte() != 0xfe);
 

	
 
        /* read up to the data of interest */
 
        for(uint16_t i = 0; i < block_offset; ++i)
 
            sd_raw_rec_byte();
 

	
 
        /* read interval bytes of data and execute the callback */
 
        do
 
        {
 
            if(read_length < interval || length < interval)
 
                break;
 

	
 
            buffer_cur = buffer;
 
            for(uint16_t i = 0; i < interval; ++i)
 
                *buffer_cur++ = sd_raw_rec_byte();
 

	
 
            if(!callback(buffer, offset + (512 - read_length), p))
 
            {
 
                finished = 1;
 
                break;
 
            }
 

	
 
            read_length -= interval;
 
            length -= interval;
 

	
 
        } while(read_length > 0 && length > 0);
 
        
 
        /* read rest of data block */
 
        while(read_length-- > 0)
 
            sd_raw_rec_byte();
 
        
 
        /* read crc16 */
 
        sd_raw_rec_byte();
 
        sd_raw_rec_byte();
 

	
 
        if(length < interval)
 
            break;
 

	
 
        offset = offset - block_offset + 512;
 

	
 
    } while(!finished);
 
    
 
    /* deaddress card */
 
    unselect_card();
 

	
 
    /* let card some time to finish */
 
    sd_raw_rec_byte();
 

	
 
    return 1;
 
#endif
 
}
 

	
 
#if DOXYGEN || SD_RAW_WRITE_SUPPORT
 
/**
 
 * \ingroup sd_raw
 
 * Writes raw data to the card.
 
 *
 
 * \note If write buffering is enabled, you might have to
 
 *       call sd_raw_sync() before disconnecting the card
 
 *       to ensure all remaining data has been written.
 
 *
 
 * \param[in] offset The offset where to start writing.
 
 * \param[in] buffer The buffer containing the data to be written.
 
 * \param[in] length The number of bytes to write.
 
 * \returns 0 on failure, 1 on success.
 
 * \see sd_raw_write_interval, sd_raw_read, sd_raw_read_interval
 
 */
 
uint8_t sd_raw_write(offset_t offset, const uint8_t* buffer, uintptr_t length)
 
{
 
    if(sd_raw_locked())
 
        return 0;
 

	
 
    offset_t block_address;
 
    uint16_t block_offset;
 
    uint16_t write_length;
 
    while(length > 0)
 
    {
 
        /* determine byte count to write at once */
 
        block_offset = offset & 0x01ff;
 
        block_address = offset - block_offset;
 
        write_length = 512 - block_offset; /* write up to block border */
 
        if(write_length > length)
 
            write_length = length;
 
        
 
        /* Merge the data to write with the content of the block.
 
         * Use the cached block if available.
 
         */
 
        if(block_address != raw_block_address)
 
        {
 
#if SD_RAW_WRITE_BUFFERING
 
            if(!sd_raw_sync())
 
                return 0;
 
#endif
 

	
 
            if(block_offset || write_length < 512)
 
            {
 
                if(!sd_raw_read(block_address, raw_block, sizeof(raw_block)))
 
                    return 0;
 
            }
 
            raw_block_address = block_address;
 
        }
 

	
 
        if(buffer != raw_block)
 
        {
 
            memcpy(raw_block + block_offset, buffer, write_length);
 

	
 
#if SD_RAW_WRITE_BUFFERING
 
            raw_block_written = 0;
 

	
 
            if(length == write_length)
 
                return 1;
 
#endif
 
        }
 

	
 
        /* address card */
 
        select_card();
 

	
 
        /* send single block request */
 
#if SD_RAW_SDHC
 
        if(sd_raw_send_command(CMD_WRITE_SINGLE_BLOCK, (sd_raw_card_type & (1 << SD_RAW_SPEC_SDHC) ? block_address / 512 : block_address)))
 
#else
 
        if(sd_raw_send_command(CMD_WRITE_SINGLE_BLOCK, block_address))
 
#endif
 
        {
 
            unselect_card();
 
            return 0;
 
        }
 

	
 
        /* send start byte */
 
        sd_raw_send_byte(0xfe);
 

	
 
        /* write byte block */
 
        uint8_t* cache = raw_block;
 
        for(uint16_t i = 0; i < 512; ++i)
 
            sd_raw_send_byte(*cache++);
 

	
 
        /* write dummy crc16 */
 
        sd_raw_send_byte(0xff);
 
        sd_raw_send_byte(0xff);
 

	
 
        /* wait while card is busy */
 
        while(sd_raw_rec_byte() != 0xff);
 
        sd_raw_rec_byte();
 

	
 
        /* deaddress card */
 
        unselect_card();
 

	
 
        buffer += write_length;
 
        offset += write_length;
 
        length -= write_length;
 

	
 
#if SD_RAW_WRITE_BUFFERING
 
        raw_block_written = 1;
 
#endif
 
    }
 

	
 
    return 1;
 
}
 
#endif
 

	
 
#if DOXYGEN || SD_RAW_WRITE_SUPPORT
 
/**
 
 * \ingroup sd_raw
 
 * Writes a continuous data stream obtained from a callback function.
 
 *
 
 * This function starts writing at the specified offset. To obtain the
 
 * next bytes to write, it calls the callback function. The callback fills the
 
 * provided data buffer and returns the number of bytes it has put into the buffer.
 
 *
 
 * By returning zero, the callback may stop writing.
 
 *
 
 * \param[in] offset Offset where to start writing.
 
 * \param[in] buffer Pointer to a buffer which is used for the callback function.
 
 * \param[in] length Number of bytes to write in total. May be zero for endless writes.
 
 * \param[in] callback The function used to obtain the bytes to write.
 
 * \param[in] p An opaque pointer directly passed to the callback function.
 
 * \returns 0 on failure, 1 on success
 
 * \see sd_raw_read_interval, sd_raw_write, sd_raw_read
 
 */
 
uint8_t sd_raw_write_interval(offset_t offset, uint8_t* buffer, uintptr_t length, sd_raw_write_interval_handler_t callback, void* p)
 
{
 
#if SD_RAW_SAVE_RAM
 
    #error "SD_RAW_WRITE_SUPPORT is not supported together with SD_RAW_SAVE_RAM"
 
#endif
 

	
 
    if(!buffer || !callback)
 
        return 0;
 

	
 
    uint8_t endless = (length == 0);
 
    while(endless || length > 0)
 
    {
 
        uint16_t bytes_to_write = callback(buffer, offset, p);
 
        if(!bytes_to_write)
 
            break;
 
        if(!endless && bytes_to_write > length)
 
            return 0;
 

	
 
        /* as writing is always buffered, we directly
 
         * hand over the request to sd_raw_write()
 
         */
 
        if(!sd_raw_write(offset, buffer, bytes_to_write))
 
            return 0;
 

	
 
        offset += bytes_to_write;
 
        length -= bytes_to_write;
 
    }
 

	
 
    return 1;
 
}
 
#endif
 

	
 
#if DOXYGEN || SD_RAW_WRITE_SUPPORT
 
/**
 
 * \ingroup sd_raw
 
 * Writes the write buffer's content to the card.
 
 *
 
 * \note When write buffering is enabled, you should
 
 *       call this function before disconnecting the
 
 *       card to ensure all remaining data has been
 
 *       written.
 
 *
 
 * \returns 0 on failure, 1 on success.
 
 * \see sd_raw_write
 
 */
 
uint8_t sd_raw_sync()
 
{
 
#if SD_RAW_WRITE_BUFFERING
 
    if(raw_block_written)
 
        return 1;
 
    if(!sd_raw_write(raw_block_address, raw_block, sizeof(raw_block)))
 
        return 0;
 
    raw_block_written = 1;
 
#endif
 
    return 1;
 
}
 
#endif
 

	
 
/**
 
 * \ingroup sd_raw
 
 * Reads informational data from the card.
 
 *
 
 * This function reads and returns the card's registers
 
 * containing manufacturing and status information.
 
 *
 
 * \note: The information retrieved by this function is
 
 *        not required in any way to operate on the card,
 
 *        but it might be nice to display some of the data
 
 *        to the user.
 
 *
 
 * \param[in] info A pointer to the structure into which to save the information.
 
 * \returns 0 on failure, 1 on success.
 
 */
 
uint8_t sd_raw_get_info(struct sd_raw_info* info)
 
{
 
    if(!info || !sd_raw_available())
 
        return 0;
 

	
 
    memset(info, 0, sizeof(*info));
 

	
 
    select_card();
 

	
 
    /* read cid register */
 
    if(sd_raw_send_command(CMD_SEND_CID, 0))
 
    {
 
        unselect_card();
 
        return 0;
 
    }
 
    while(sd_raw_rec_byte() != 0xfe);
 
    for(uint8_t i = 0; i < 18; ++i)
 
    {
 
        uint8_t b = sd_raw_rec_byte();
 

	
 
        switch(i)
 
        {
 
            case 0:
 
                info->manufacturer = b;
 
                break;
 
            case 1:
 
            case 2:
 
                info->oem[i - 1] = b;
 
                break;
 
            case 3:
 
            case 4:
 
            case 5:
 
            case 6:
 
            case 7:
 
                info->product[i - 3] = b;
 
                break;
 
            case 8:
 
                info->revision = b;
 
                break;
 
            case 9:
 
            case 10:
 
            case 11:
 
            case 12:
 
                info->serial |= (uint32_t) b << ((12 - i) * 8);
 
                break;
 
            case 13:
 
                info->manufacturing_year = b << 4;
 
                break;
 
            case 14:
 
                info->manufacturing_year |= b >> 4;
 
                info->manufacturing_month = b & 0x0f;
 
                break;
 
        }
 
    }
 

	
 
    /* read csd register */
 
    uint8_t csd_read_bl_len = 0;
 
    uint8_t csd_c_size_mult = 0;
 
#if SD_RAW_SDHC
 
    uint16_t csd_c_size = 0;
 
#else
 
    uint32_t csd_c_size = 0;
 
#endif
 
    uint8_t csd_structure = 0;
 
    if(sd_raw_send_command(CMD_SEND_CSD, 0))
 
    {
 
        unselect_card();
 
        return 0;
 
    }
 
    while(sd_raw_rec_byte() != 0xfe);
 
    for(uint8_t i = 0; i < 18; ++i)
 
    {
 
        uint8_t b = sd_raw_rec_byte();
 

	
 
        if(i == 0)
 
        {
 
            csd_structure = b >> 6;
 
        }
 
        else if(i == 14)
 
        {
 
            if(b & 0x40)
 
                info->flag_copy = 1;
 
            if(b & 0x20)
 
                info->flag_write_protect = 1;
 
            if(b & 0x10)
 
                info->flag_write_protect_temp = 1;
 
            info->format = (b & 0x0c) >> 2;
 
        }
 
        else
 
        {
 
#if SD_RAW_SDHC
 
            if(csd_structure == 0x01)
 
            {
 
                switch(i)
 
                {
 
                    case 7:
 
                        b &= 0x3f;
 
                    case 8:
 
                    case 9:
 
                        csd_c_size <<= 8;
 
                        csd_c_size |= b;
 
                        break;
 
                }
 
                if(i == 9)
 
                {
 
                    ++csd_c_size;
 
                    info->capacity = (offset_t) csd_c_size * 512 * 1024;
 
                }
master/master/lib/serial.c
Show inline comments
 
/*
 
 * serial.c
 
 *
 
 * Created: 10/25/2012 3:19:49 PM
 
 *  Author: ethanzonca
 
 */ 
 
 
#include "serial.h"
 
#include "../config.h"
 
#include <avr/io.h>
 
 
 
void serial0_setup() {
 
	/* Set baud rate */
 
	UBRR0H = (unsigned char)(USART0_BAUD_PRESCALE>>8);
 
	UBRR0L = (unsigned char)USART0_BAUD_PRESCALE;
 
	/* Enable receiver and transmitter */
 
	UCSR0B = (1<<RXEN0)|(1<<TXEN0);
 
	/* Set frame format: 8data, 1stop bit */
 
	UCSR0C = (3<<UCSZ00); // - 1 stop bit
 
}
 
 
void serial1_setup() {
 
	/* Set baud rate */
 
	UBRR1H = (unsigned char)(USART1_BAUD_PRESCALE>>8);
 
	UBRR1L = (unsigned char)USART1_BAUD_PRESCALE;
 
	/* Enable receiver and transmitter */
 
	UCSR1B = (1<<RXEN1)|(1<<TXEN1);
 
	/* Set frame format: 8data, 1stop bit */
 
	UCSR1C = (3<<UCSZ10); // - 1 stop bit
 
}
 
 
void serial0_sendChar( unsigned char byte )
 
{
 
	while (!(UCSR0A & (1<<UDRE0)));
 
	UDR0 = byte;
 
}
 
 
void serial1_sendChar( unsigned char byte )
 
{
 
	while (!(UCSR1A & (1<<UDRE1)));
 
	UDR1 = byte;
 
}
 
 
void serial0_sendString(char* stringPtr){
 
unsigned char serial0_readChar()
 
{
 
	while(!(UCSR0A &(1<<RXC0)));
 
	return UDR0;
 
}
 
 
unsigned char serial1_readChar()
 
{
 
	while(!(UCSR1A &(1<<RXC1)));
 
	return UDR1;
 
}
 
 
void serial0_sendString(const char* stringPtr){
 
	while(*stringPtr != 0x00){
 
		serial0_sendChar(*stringPtr);
 
		stringPtr++;
 
	}
 
}
 
 
void serial1_sendString(char* stringPtr){
 
void serial1_sendString(const char* stringPtr){
 
	while(*stringPtr != 0x00){
 
		serial1_sendChar(*stringPtr);
 
		stringPtr++;
 
	}
 
}
 
 
 
void serial_sendCommand( char moduleID, char sensorID, uint8_t dataLength, char* data )
 
void serial_sendCommand( char moduleID, char sensorID, char* data )
 
{
 
	char checkSum = 0x00; //initialize checksum
 
	
 
	serial0_sendChar('['); //bracket indicates start of command
 
	serial0_sendChar(moduleID);
 
	checkSum+=moduleID;
 
	
 
	serial0_sendChar(sensorID);
 
	checkSum+=sensorID;
 
	
 
	//send each character of data individually
 
	for (int i=0; i<dataLength; i++)
 
	{
 
		serial0_sendChar(data[i]);
 
		checkSum+=data[i];
 
	// send data, null-terminated
 
	while(*data != 0x00){
 
		serial0_sendChar(*data);
 
		checkSum += *data;
 
		data++;
 
	}
 
	
 
	serial0_sendChar(checkSum);
 
	serial0_sendChar(']'); //bracket indicates end of command
 
}
 
 
void serial_sendResponseData(){
 
	
 
}
 
master/master/lib/serial.h
Show inline comments
 
/*
 
 * serial.h
 
 *
 
 * Created: 10/25/2012 3:19:42 PM
 
 *  Author: ethanzonca
 
 */ 
 
 
 
#ifndef SERIAL_H_
 
#define SERIAL_H_
 
 
#include <inttypes.h>
 
 
#define USART0_BAUD_PRESCALE (((F_CPU / (USART0_BAUDRATE * 16UL))) -1 )
 
#define USART1_BAUD_PRESCALE (((F_CPU / (USART1_BAUDRATE * 16UL))) -1 )
 
 
void serial0_sendChar( unsigned char byte );
 
void serial1_sendChar( unsigned char byte );
 
 
unsigned char serial0_readChar();
 
unsigned char serial1_readChar();
 
 
void serial0_setup();
 
void serial1_setup();
 
 
void serial0_sendString(char* stringPtr);
 
void serial1_sendString(char* stringPtr);
 
void serial0_sendString(const char* stringPtr);
 
void serial1_sendString(const char* stringPtr);
 
 
void serial_sendCommand( char moduleID, char sensorID, uint8_t dataLength, char* data );
 
void serial_sendCommand( char moduleID, char sensorID, char* data );
 
void serial_sendResponseData();
 
 
 
#endif /* SERIAL_H_ */
 
\ No newline at end of file
master/master/lib/serparser.c
Show inline comments
 
/*
 
* serparser.c
 
*
 
* Created: 10/25/2012 8:11:43 PM
 
*  Author: ethanzonca
 
*/
 
 
 
// ************* Macros ***************
 
#define SERIAL_RX_HASBYTES UCSR0A & _BV(RXC0)
 
#define MAX_CMD_LEN 16
 
#define BROADCAST_ADDR 0 //public address
 
#include <avr/io.h>
 
#include "../config.h"
 
 
#include "serial.h"
 
//#define DEBUG
 
 
// ************* Command Definitions ***************
 
 
// Serial Commands
 
enum cmd // CMD ID#
 
{
 
	BOARDTEMP = 0, // 0
 
	PRESSURE,      // 1
 
};
 
 
// Incoming command buffer
 
uint8_t buffer[MAX_CMD_LEN+2];
 
 
// Current buffer location
 
uint8_t bufferPosition = 0;
 
 
//current length of the data transmission (and checksum)
 
int dataLength;
 
 
//data (and checksum) of most recent transmission
 
char data[16];
 
 
//ID of the sensor of most recent transmission
 
char sensorID;
 
 
//checksum to be calculated and then compared to the received checksum
 
char checksumCalc;
 
 
/* return char from UART (h/w buffer) */
 
uint8_t uart_getchar(void)
 
{
 
	// Wait for chars
 
	/*	while (!(UCSRA & (1<<RXC)))
 
	{
 
		idle();
 
	}
 
	return UDR;
 
	*/
 
	return 0;
 
}
 
 
/* Process incoming serial data */
 
int uart_Parser(void)
 
// TODO: Maybe make this suck up the whole buffer if there is more to be had. That would make this much more efficient.
 
// we could parse while(SERIAL_RX_HASBYTES && notOverTimeout), don't have it parse for more than 100ms straight or something...
 
int serparser_parse(void)
 
{
 
 
	char byte;
 
 
	if(SERIAL_RX_HASBYTES) // Only process data if buffer has a byte
 
	{
 
		
 
		// Pull byte off of the buffer
 
		byte = uart_getchar();
 
		byte = serial0_readChar();
 
		buffer[bufferPosition] = byte;
 
		
 
		// byte checking/validation
 
		if(bufferPosition == 0)
 
		{
 
			if(byte == '[') // If this is a start byte, we're OK. Keep reading.
 
			{
 
				bufferPosition++;
 
			}
 
			else // Not a start byte that we're expecting. Reset to initial state.
 
			{
 
				bufferPosition = 0;
 
			}
 
		}
 
		else if(bufferPosition == 1)
 
		{
 
			if(byte == MODULE_ID) //this transmission is intended for the master; continue parsing
 
			{
 
				bufferPosition++;
 
				checksumCalc += byte;
 
				dataLength = 0; //reset dataLength here to protect from bad inputs
 
			}
 
			else //this transmission is intended for another module; stop parsing and reset
 
			{
 
				bufferPosition = 0;
 
			}
 
		}
 
		else if(bufferPosition == 2)
 
		{
 
			sensorID = byte; //store the type of data receiving
 
			bufferPosition++;
 
			checksumCalc += byte;
 
		}
 
		else if (bufferPosition == MAX_CMD_LEN) //command is too long and bad data has been recieved; reset
 
		{
 
			bufferPosition = 0;
 
		}
 
		else
 
		{
 
			if (byte == ']') //this is the end of the transmission
 
			{
 
				bufferPosition = 0;
 
				return 2; // got whole msg
 
			}
 
			else //still receiving data
 
			{
 
				data[dataLength] = byte;
 
				dataLength++;
 
				bufferPosition++;
 
				checksumCalc += byte;
 
			}
 
 
		}
 
	}
 
	else
 
	{
 
		return 0; // serial data not available
 
	}
 
}
 
\ No newline at end of file
master/master/lib/serparser.h
Show inline comments
 
/*
 
 * serparser.h
 
 *
 
 * Created: 10/25/2012 8:11:49 PM
 
 *  Author: ethanzonca
 
 */ 
 
 
 
#ifndef SERPARSER_H_
 
#define SERPARSER_H_
 
 
 
// Prototypes
 
uint8_t convertchar(uint8_t);
 
uint8_t uart_getchar(void);
 
void got_char(uint8_t);
 
int uart_machine(void);
 
void uart_putchar(uint8_t);
 
void exec_cmd(void);
 
void idle(void);
 
void uart_init(void);
 
 
 
int serparser_parse(void);
 
 
#endif /* SERPARSER_H_ */
 
\ No newline at end of file
master/master/lib/slavesensors.c
Show inline comments
 
new file 100644
 
/*
 
 * slavesensors.c
 
 *
 
 * Created: 11/27/2012 9:02:12 PM
 
 *  Author: ethanzonca
 
 */ 
 
 
#include <avr/io.h>
 
#include <stdbool.h>
 
#include "../config.h"
 
#include "serial.h"
 
#include "serparser.h"
 

	
 
// Serial Commands
 
enum sensorTypes // CMD ID#
 
{
 
	NONE = 0,
 
	BOARDTEMP = (1<<0),
 
	PRESSURE = (1<<1),
 
	GEIGER = (1<<2),
 
	TEMPERATURE = (1<<3),
 
	HUMIDITY = (1<<4),
 
	AMBIENTLIGHT = (1<<5),
 
	CAMERA = (1<<5),
 
};
 

	
 
uint8_t receptionFinished = 0;
 
uint8_t currentSlave = 0;
 
uint8_t currentSlaveSensor = 0;
 
 
uint8_t maxSlave = 8;
 
uint16_t slaves[8];
 
 
void slavesensors_setup() 
 
{
 
	// Empty array
 
	for(int i=0; i<8; i++) 
 
	{
 
		slaves[i] = 0;
 
	}	
 
	
 
	// Configure sensors
 
	slaves[0] = SLAVE0_SENSORS;
 
	slaves[1] = SLAVE1_SENSORS;
 
	slaves[2] = SLAVE2_SENSORS;
 
	slaves[3] = SLAVE3_SENSORS;
 
	slaves[4] = SLAVE4_SENSORS;
 
	slaves[5] = SLAVE5_SENSORS;
 
	slaves[6] = SLAVE6_SENSORS;
 
	slaves[7] = SLAVE7_SENSORS;	
 
}
 
 
bool slavesensors_process() 
 
{
 
	// Periodic: Every Iteration
 
		
 
	// maybe we should do this in an ISR on byte received. only problem is that this could interrupt things,
 
	// but we only care about interruption during logging and such. don't log when parsing a message?
 
	receptionFinished = serparser_parse();
 
		
 
	// Finished reception of a message (one sensor data value). If not finished, send out command to get the next one
 
	if(receptionFinished == 2)
 
	{
 
		bool weFinishedTHeLastSlaveSensor = false; // ex.
 
		// if we finished the final reception for this slave, set gettingValues = false;
 
		if(currentSlave >= maxSlave && weFinishedTHeLastSlaveSensor)
 
		{
 
			currentSlave = 0;
 
			return false; // We're done for now!
 
		}
 
		else
 
		{
 
			// Request data from the next slave
 
			currentSlave++;
 
			
 
			// Need to check the next bit over to see if it has that...
 
			
 
			serial_sendCommand(currentSlave, 'a', ""); // send req for data
 
			return true; // Keep going...
 
		}
 
	}
 
	else 
 
	{
 
		return true; // Keep going...
 
	}
 
}		
 
\ No newline at end of file
master/master/lib/slavesensors.h
Show inline comments
 
new file 100644
 
/*
 
 * slavesensors.h
 
 *
 
 * Created: 11/27/2012 9:05:47 PM
 
 *  Author: ethanzonca
 
 */ 
 
 
 
#ifndef SLAVESENSORS_H_
 
#define SLAVESENSORS_H_
 
 
#include <stdbool.h>
 
 
void slavesensors_setup();
 
bool slavesensors_process();
 
 
 
#endif /* SLAVESENSORS_H_ */
 
\ 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 "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/sd/sd_raw_config.h"
 
#include "lib/looptime.h"
 
#include "lib/slavesensors.h"
 

	
 
void micro_setup() {
 

	
 
}
 

	
 
int main(void)
 
{
 
    
 
	// Initialize. If this takes more than 4 seconds, be sure to reset the WDT
 
	// Initialize libraries
 
	time_setup();
 
	micro_setup();
 
	watchdog_setup();
 
	led_setup();
 
	serial0_setup(); // Config serial ports
 
	serial1_setup(); // Config serial ports
 
	logger_setup(); // this takes a few ms
 
	afsk_setup(); // can take a few ms
 
	serial0_setup();
 
	serial1_setup();
 
	slavesensors_setup();
 
	logger_setup();
 
	afsk_setup();
 

	
 
	serial0_sendString("\r\n\r\n---------------------------------\r\nHAB Controller 1.0 - Initialized!\r\n---------------------------------\r\n\r\n");
 
	
 
	led_on(POWER);
 
	
 
	uint16_t ctr1 = 0;
 
	uint16_t ctr2 = 255;
 
	// Buffer for string operations
 
	char logbuf[32];
 
	const char* logBufPtr = logbuf;
 
		
 
	char logbuf[32];
 
	
 
	// Software timers	
 
	uint32_t lastAprsBroadcast = 0;
 
	uint32_t lastLog = 0;
 
	
 
	// If we are currently processing sensor data
 
	bool isProcessing = false;
 
	
 
	// Write CSV header to SD card
 
	logger_log("ProgramTime,LastAprsBroadcast,LastLog\n");
 
	
 
	while(1)
 
    {
 
		
 
		if(time_millis() - lastLog > 1000) {
 
		// Periodic: Logging
 
		if(time_millis() - lastLog > LOGGER_RATE) {
 
			
 
			// TODO: Acquire data from daughterboards
 
			//       This will be complicated because we need timeouts / unreliable transmission, etc
 
			//
 
			// For each daughterboard...
 
			//   1. Send request to daughterboard for sensor data
 
			//   2. Wait for response from daughterboard (timeout!)
 
			//   3. Put data into local variables for transmission / logging
 
			
 
			led_on(STAT);
 
			sprintf(logbuf, "%lu,%u,%u,%u,%u,%u\r\n", time_millis(),5*ctr1,ctr2, 12*ctr2,43*ctr1,5*ctr2);
 
			snprintf(logbuf, 32, "%lu,%lu,%lu,\r\n", time_millis(), lastAprsBroadcast,lastLog);
 
			logger_log(logbuf);
 
			serial0_sendString("SD Logger: ");
 
			serial0_sendString(logbuf);
 
			serial0_sendString(logBufPtr);
 
			led_off(STAT);
 
			lastLog = time_millis();
 
		}		
 
		
 
		// 8 second periodic for APRS transmission
 
		// for some reason this seems to lock up and the WDT resets everything when the period exceeds 8 seconds. Which is the WDTimeout. Weird.
 
		// If we want ~8+ seconds, then we'll need to do something fun here. Maybe reset the wdt...
 
		if(time_millis() - lastAprsBroadcast > 10000) {
 
		// Periodic: APRS transmission
 
		if(time_millis() - lastAprsBroadcast > APRS_TRANSMIT_PERIOD) {
 
			while(afsk_busy());
 
			aprs_send(); // non-blocking
 
			serial0_sendString("Initiating APRS transmission...\r\n");
 
			
 
			// Start getting values for next transmission
 
			isProcessing = true;
 
			
 
			lastAprsBroadcast = time_millis();
 
		}			
 
		
 
		ctr1++;
 
		ctr2-=6;
 
		// keep calling processSensors until it is finished
 
		if(isProcessing) 
 
		{
 
			isProcessing = slavesensors_process();
 
		}
 
		wdt_reset();
 
    }
 
}
 
\ No newline at end of file
master/master/master.cproj
Show inline comments
 
<?xml version="1.0" encoding="utf-8"?>
 
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
 
  <PropertyGroup>
 
    <SchemaVersion>2.0</SchemaVersion>
 
    <ProjectVersion>6.0</ProjectVersion>
 
    <ToolchainName>com.Atmel.AVRGCC8</ToolchainName>
 
    <ProjectGuid>{8579ec2d-5815-40db-84e0-1d14239c7aea}</ProjectGuid>
 
    <avrdevice>ATmega324P</avrdevice>
 
    <avrdeviceseries>none</avrdeviceseries>
 
    <OutputType>Executable</OutputType>
 
    <Language>C</Language>
 
    <OutputFileName>$(MSBuildProjectName)</OutputFileName>
 
    <OutputFileExtension>.elf</OutputFileExtension>
 
    <OutputDirectory>$(MSBuildProjectDirectory)\$(Configuration)</OutputDirectory>
 
    <AssemblyName>master</AssemblyName>
 
    <Name>master</Name>
 
    <RootNamespace>master</RootNamespace>
 
    <ToolchainFlavour>Native</ToolchainFlavour>
 
    <KeepTimersRunning>true</KeepTimersRunning>
 
    <OverrideVtor>false</OverrideVtor>
 
    <OverrideVtorValue />
 
    <eraseonlaunchrule>0</eraseonlaunchrule>
 
    <AsfVersion>3.1.3</AsfVersion>
 
    <avrtool>com.atmel.avrdbg.tool.ispmk2</avrtool>
 
    <avrtoolinterface>ISP</avrtoolinterface>
 
    <com_atmel_avrdbg_tool_simulator>
 
      <ToolType xmlns="">com.atmel.avrdbg.tool.simulator</ToolType>
 
      <ToolName xmlns="">AVR Simulator</ToolName>
 
      <ToolNumber xmlns="">
 
      </ToolNumber>
 
      <KeepTimersRunning xmlns="">true</KeepTimersRunning>
 
      <OverrideVtor xmlns="">false</OverrideVtor>
 
      <OverrideVtorValue xmlns="">
 
      </OverrideVtorValue>
 
      <Channel xmlns="">
 
        <host>127.0.0.1</host>
 
        <port>52692</port>
 
        <ssl>False</ssl>
 
      </Channel>
 
    </com_atmel_avrdbg_tool_simulator>
 
    <com_atmel_avrdbg_tool_ispmk2>
 
      <ToolType>com.atmel.avrdbg.tool.ispmk2</ToolType>
 
      <ToolName>AVRISP mkII</ToolName>
 
      <ToolNumber>000200131077</ToolNumber>
 
      <KeepTimersRunning>true</KeepTimersRunning>
 
      <OverrideVtor>false</OverrideVtor>
 
      <OverrideVtorValue>
 
      </OverrideVtorValue>
 
      <Channel>
 
        <host>127.0.0.1</host>
 
        <port>61309</port>
 
        <ssl>False</ssl>
 
      </Channel>
 
      <ToolOptions>
 
        <InterfaceName>ISP</InterfaceName>
 
        <InterfaceProperties>
 
          <JtagDbgClock>249000</JtagDbgClock>
 
          <JtagProgClock>1000000</JtagProgClock>
 
          <IspClock>2010000</IspClock>
 
          <JtagInChain>false</JtagInChain>
 
          <JtagEnableExtResetOnStartSession>false</JtagEnableExtResetOnStartSession>
 
          <JtagDevicesBefore>0</JtagDevicesBefore>
 
          <JtagDevicesAfter>0</JtagDevicesAfter>
 
          <JtagInstrBitsBefore>0</JtagInstrBitsBefore>
 
          <JtagInstrBitsAfter>0</JtagInstrBitsAfter>
 
        </InterfaceProperties>
 
      </ToolOptions>
 
    </com_atmel_avrdbg_tool_ispmk2>
 
    <preserveEEPROM>True</preserveEEPROM>
 
  </PropertyGroup>
 
  <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
 
    <ToolchainSettings>
 
      <AvrGcc>
 
        <avrgcc.common.outputfiles.hex>True</avrgcc.common.outputfiles.hex>
 
        <avrgcc.common.outputfiles.lss>True</avrgcc.common.outputfiles.lss>
 
        <avrgcc.common.outputfiles.eep>True</avrgcc.common.outputfiles.eep>
 
        <avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>True</avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>
 
        <avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>True</avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>
 
        <avrgcc.compiler.optimization.level>Optimize for size (-Os)</avrgcc.compiler.optimization.level>
 
        <avrgcc.compiler.optimization.PackStructureMembers>True</avrgcc.compiler.optimization.PackStructureMembers>
 
        <avrgcc.compiler.optimization.AllocateBytesNeededForEnum>True</avrgcc.compiler.optimization.AllocateBytesNeededForEnum>
 
        <avrgcc.compiler.warnings.AllWarnings>True</avrgcc.compiler.warnings.AllWarnings>
 
        <avrgcc.linker.libraries.Libraries>
 
          <ListValues>
 
            <Value>m</Value>
 
          </ListValues>
 
        </avrgcc.linker.libraries.Libraries>
 
      </AvrGcc>
 
    </ToolchainSettings>
 
  </PropertyGroup>
 
  <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
 
    <ToolchainSettings>
 
      <AvrGcc>
 
        <avrgcc.common.outputfiles.hex>True</avrgcc.common.outputfiles.hex>
 
        <avrgcc.common.outputfiles.lss>True</avrgcc.common.outputfiles.lss>
 
        <avrgcc.common.outputfiles.eep>True</avrgcc.common.outputfiles.eep>
 
        <avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>True</avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>
 
        <avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>True</avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>
 
        <avrgcc.compiler.optimization.level>Optimize (-O1)</avrgcc.compiler.optimization.level>
 
        <avrgcc.compiler.optimization.PackStructureMembers>True</avrgcc.compiler.optimization.PackStructureMembers>
 
        <avrgcc.compiler.optimization.AllocateBytesNeededForEnum>True</avrgcc.compiler.optimization.AllocateBytesNeededForEnum>
 
        <avrgcc.compiler.optimization.DebugLevel>Default (-g2)</avrgcc.compiler.optimization.DebugLevel>
 
        <avrgcc.compiler.warnings.AllWarnings>True</avrgcc.compiler.warnings.AllWarnings>
 
        <avrgcc.linker.libraries.Libraries>
 
          <ListValues>
 
            <Value>m</Value>
 
          </ListValues>
 
        </avrgcc.linker.libraries.Libraries>
 
        <avrgcc.assembler.debugging.DebugLevel>Default (-Wa,-g)</avrgcc.assembler.debugging.DebugLevel>
 
      </AvrGcc>
 
    </ToolchainSettings>
 
  </PropertyGroup>
 
  <ItemGroup>
 
    <Compile Include="config.h">
 
      <SubType>compile</SubType>
 
    </Compile>
 
    <Compile Include="lib\afsk.c">
 
      <SubType>compile</SubType>
 
    </Compile>
 
    <Compile Include="lib\afsk.h">
 
      <SubType>compile</SubType>
 
    </Compile>
 
    <Compile Include="lib\aprs.c">
 
      <SubType>compile</SubType>
 
    </Compile>
 
    <Compile Include="lib\aprs.h">
 
      <SubType>compile</SubType>
 
    </Compile>
 
    <Compile Include="lib\ax25.c">
 
      <SubType>compile</SubType>
 
    </Compile>
 
    <Compile Include="lib\ax25.h">
 
      <SubType>compile</SubType>
 
    </Compile>
 
    <Compile Include="lib\logger.c">
 
      <SubType>compile</SubType>
 
    </Compile>
 
    <Compile Include="lib\led.c">
 
      <SubType>compile</SubType>
 
    </Compile>
 
    <Compile Include="lib\led.h">
 
      <SubType>compile</SubType>
 
    </Compile>
 
    <Compile Include="lib\logger.h">
 
      <SubType>compile</SubType>
 
    </Compile>
 
    <Compile Include="lib\looptime.c">
 
      <SubType>compile</SubType>
 
    </Compile>
 
    <Compile Include="lib\looptime.h">
 
      <SubType>compile</SubType>
 
    </Compile>
 
    <Compile Include="lib\sd\byteordering.c">
 
      <SubType>compile</SubType>
 
    </Compile>
 
    <Compile Include="lib\sd\byteordering.h">
 
      <SubType>compile</SubType>
 
    </Compile>
 
    <Compile Include="lib\sd\fat.c">
 
      <SubType>compile</SubType>
 
    </Compile>
 
    <Compile Include="lib\sd\fat.h">
 
      <SubType>compile</SubType>
 
    </Compile>
 
    <Compile Include="lib\sd\fat_config.h">
 
      <SubType>compile</SubType>
 
    </Compile>
 
    <Compile Include="lib\sd\partition.c">
 
      <SubType>compile</SubType>
 
    </Compile>
 
    <Compile Include="lib\sd\partition.h">
 
      <SubType>compile</SubType>
 
    </Compile>
 
    <Compile Include="lib\sd\partition_config.h">
 
      <SubType>compile</SubType>
 
    </Compile>
 
    <Compile Include="lib\sd\sd-reader_config.h">
 
      <SubType>compile</SubType>
 
    </Compile>
 
    <Compile Include="lib\sd\sd_raw.c">
 
      <SubType>compile</SubType>
 
    </Compile>
 
    <Compile Include="lib\sd\sd_raw.h">
 
      <SubType>compile</SubType>
 
    </Compile>
 
    <Compile Include="lib\sd\sd_raw_config.h">
 
      <SubType>compile</SubType>
 
    </Compile>
 
    <Compile Include="lib\serial.c">
 
      <SubType>compile</SubType>
 
    </Compile>
 
    <Compile Include="lib\serial.h">
 
      <SubType>compile</SubType>
 
    </Compile>
 
    <Compile Include="lib\serparser.c">
 
      <SubType>compile</SubType>
 
    </Compile>
 
    <Compile Include="lib\serparser.h">
 
      <SubType>compile</SubType>
 
    </Compile>
 
    <Compile Include="lib\slavesensors.c">
 
      <SubType>compile</SubType>
 
    </Compile>
 
    <Compile Include="lib\slavesensors.h">
 
      <SubType>compile</SubType>
 
    </Compile>
 
    <Compile Include="lib\trackuinoGPS\config.h">
 
      <SubType>compile</SubType>
 
    </Compile>
 
    <Compile Include="lib\trackuinoGPS\gpsMKa.c">
 
      <SubType>compile</SubType>
 
    </Compile>
 
    <Compile Include="lib\trackuinoGPS\gpsMKa.h">
 
      <SubType>compile</SubType>
 
    </Compile>
 
    <Compile Include="lib\watchdog.c">
 
      <SubType>compile</SubType>
 
    </Compile>
 
    <Compile Include="lib\watchdog.h">
 
      <SubType>compile</SubType>
 
    </Compile>
 
    <Compile Include="master.c">
 
      <SubType>compile</SubType>
 
    </Compile>
 
  </ItemGroup>
 
  <ItemGroup>
 
    <Folder Include="lib" />
 
    <Folder Include="lib\trackuinoGPS" />
 
    <Folder Include="lib\sd" />
 
  </ItemGroup>
 
  <Import Project="$(AVRSTUDIO_EXE_PATH)\\Vs\\Compiler.targets" />
 
</Project>
 
\ No newline at end of file
0 comments (0 inline, 0 general)