Changeset - 5109fd6856e1
[Not reviewed]
default
0 6 0
ethanzonca@CL-SEC241-08.cedarville.edu - 13 years ago 2012-11-09 00:00:05
ethanzonca@CL-SEC241-08.cedarville.edu
Work on SD card
6 files changed with 75 insertions and 96 deletions:
0 comments (0 inline, 0 general)
master/master/lib/afsk.c
Show inline comments
 
@@ -26,212 +26,208 @@ PROGMEM extern const uint8_t afsk_sine_t
 
  254, 254, 255, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 253, 253, 253, 253, 252, 252, 252, 251, 
 
  251, 251, 250, 250, 249, 249, 249, 248, 248, 247, 247, 246, 245, 245, 244, 244, 243, 242, 242, 241, 240, 
 
  239, 239, 238, 237, 236, 236, 235, 234, 233, 232, 231, 230, 229, 228, 228, 227, 226, 225, 224, 223, 221, 
 
  220, 219, 218, 217, 216, 215, 214, 213, 211, 210, 209, 208, 207, 205, 204, 203, 202, 200, 199, 198, 197, 
 
  195, 194, 193, 191, 190, 188, 187, 186, 184, 183, 182, 180, 179, 177, 176, 174, 173, 171, 170, 168, 167, 
 
  166, 164, 163, 161, 159, 158, 156, 155, 153, 152, 150, 149, 147, 146, 144, 143, 141, 139, 138, 136, 135, 
 
  133, 132, 130, 129, 127, 125, 124, 122, 121, 119, 118, 116, 115, 113, 111, 110, 108, 107, 105, 104, 102, 
 
  101,  99,  98,  96,  95,  93,  91,  90,  88,  87,  86,  84,  83,  81,  80,  78,  77,  75,  74,  72,  71, 
 
   70,  68,  67,  66,  64,  63,  61,  60,  59,  57,  56,  55,  54,  52,  51,  50,  49,  47,  46,  45,  44, 
 
   43,  41,  40,  39,  38,  37,  36,  35,  34,  33,  31,  30,  29,  28,  27,  26,  26,  25,  24,  23,  22, 
 
   21,  20,  19,  18,  18,  17,  16,  15,  15,  14,  13,  12,  12,  11,  10,  10,   9,   9,   8,   7,   7, 
 
    6,   6,   5,   5,   5,   4,   4,   3,   3,   3,   2,   2,   2,   1,   1,   1,   1,   0,   0,   0,   0, 
 
    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   1,   1,   1,   1, 
 
    2,   2,   2,   3,   3,   3,   4,   4,   5,   5,   5,   6,   6,   7,   7,   8,   9,   9,  10,  10,  11, 
 
   12,  12,  13,  14,  15,  15,  16,  17,  18,  18,  19,  20,  21,  22,  23,  24,  25,  26,  26,  27,  28, 
 
   29,  30,  31,  33,  34,  35,  36,  37,  38,  39,  40,  41,  43,  44,  45,  46,  47,  49,  50,  51,  52, 
 
   54,  55,  56,  57,  59,  60,  61,  63,  64,  66,  67,  68,  70,  71,  72,  74,  75,  77,  78,  80,  81, 
 
   83,  84,  86,  87,  88,  90,  91,  93,  95,  96,  98,  99, 101, 102, 104, 105, 107, 108, 110, 111, 113, 
 
  115, 116, 118, 119, 121, 122, 124, 125
 
};
 

	
 
static inline uint8_t afsk_read_sample(int phase)
 
{
 
  return pgm_read_byte_near(afsk_sine_table + phase);
 
}
 

	
 
volatile uint16_t phase = 10;
 
volatile uint16_t phasedelta = 3300;
 
extern const uint16_t TABLE_SIZE = sizeof(afsk_sine_table);
 

	
 
// constants
 
#define MODEM_CLOCK_RATE F_CPU
 
#define PLAYBACK_RATE MODEM_CLOCK_RATE / 256  // Fast PWM
 

	
 
#define BAUD_RATE 1200
 
//#define SAMPLES_PER_BAUD PLAYBACK_RATE / BAUD_RATE // = 36
 
//#define SAMPLES_PER_BAUD 36
 
#define SAMPLES_PER_BAUD 36
 

	
 

	
 
// phase offset of 1800 gives ~1900 Hz
 
// phase offset of 3300 gives ~2200 Hz
 
#define PHASE_DELTA_1200 1800
 
#define PHASE_DELTA_2200 2200
 

	
 
// Module globals
 
volatile unsigned char current_byte;
 
volatile unsigned char current_sample_in_baud;    // 1 bit = SAMPLES_PER_BAUD samples
 
volatile bool go = false;                 
 

	
 
volatile unsigned int packet_pos;                 // Next bit to be sent out
 

	
 

	
 
volatile unsigned int afsk_packet_size = 10;
 
volatile const uint8_t *afsk_packet;
 

	
 

	
 

	
 

	
 

	
 

	
 
void afsk_ptt_off() {
 
	// turn ptt off
 
}
 

	
 
void afsk_ptt_on() {
 
	// turn the ptt on... possibly delay based on spec
 
}
 

	
 

	
 

	
 

	
 

	
 

	
 

	
 
ISR(TIMER2_OVF_vect) 
 
{
 
	if (go) {
 

	
 
		// If done sending packet
 
		if (packet_pos == afsk_packet_size) {
 
			go = false;         // End of transmission
 
			afsk_timer_stop();  // Disable modem
 
			afsk_ptt_off();    // Release PTT
 
			return; // done
 
		}
 

	
 
		// If sent SAMPLES_PER_BAUD already, go to the next bit
 
		if (current_sample_in_baud == 0) {    // Load up next bit
 
			if ((packet_pos & 7) == 0) {          // Load up next byte
 
				current_byte = afsk_packet[packet_pos >> 3];
 
			}				
 
			else {
 
				current_byte = current_byte / 2;  // ">>1" forces int conversion
 
			}			
 
			if ((current_byte & 1) == 0) {
 
				// Toggle tone (1200 <> 2200)
 
				phasedelta ^= (PHASE_DELTA_1200 ^ PHASE_DELTA_2200);
 
			}
 
		}
 
	
 
		phase += phasedelta;
 
		uint8_t s = afsk_read_sample((phase >> 7) & (TABLE_SIZE - 1));
 
		afsk_output_sample(s);
 

	
 
		if(++current_sample_in_baud == SAMPLES_PER_BAUD) {
 
			// sounds fun when this is commented out... but why??!?!
 
			current_sample_in_baud = 0;
 
			packet_pos++;
 
		}
 
		
 
	}
 
}	
 

	
 
void afsk_output_sample(uint8_t s) {
 
	OCR2B = s;
 
}
 

	
 
void afsk_timer_start()
 
{
 
	// Clear the overflow flag, so that the interrupt doesn't go off
 
	// immediately and overrun the next one (p.163).
 
	TIFR2 |= _BV(TOV2);       // Yeah, writing a 1 clears the flag.
 

	
 
	// Enable interrupt when TCNT2 reaches TOP (0xFF) (p.151, 163)
 
	TIMSK2 |= _BV(TOIE2);
 
}
 

	
 
void afsk_timer_stop()
 
{
 
	// Resting duty cycle
 
	// Output 0v (could be 255/2, which is 0v after coupling... doesn't really matter)
 
	OCR2B = 0x80;
 

	
 
	// Disable playback interrupt
 
	TIMSK2 &= ~_BV(TOIE2);
 
}
 

	
 

	
 

	
 

	
 

	
 
// External
 

	
 
void afsk_start()
 
{
 
	phasedelta = PHASE_DELTA_1200;
 
	phase = 0;
 
	packet_pos = 0;
 
	current_sample_in_baud = 0;
 
	go = true;
 

	
 
	// Key the radio
 
	afsk_ptt_on();
 

	
 
	// Start transmission
 
	afsk_timer_start();
 
}
 

	
 
int afsk_busy()
 
{
 
	return go;
 
}
 

	
 
void afsk_send(const uint8_t *buffer, int len)
 
{
 
	afsk_packet_size = len;
 
	afsk_packet = buffer;
 
}
 

	
 

	
 
void afsk_setup() {
 
	
 
	// Source timer2 from clkIO (datasheet p.164)
 
	ASSR &= ~(_BV(EXCLK) | _BV(AS2));
 

	
 
	// Set fast PWM mode with TOP = 0xff: WGM22:0 = 3  (p.150)
 
	TCCR2A |= _BV(WGM21) | _BV(WGM20);
 
	TCCR2B &= ~_BV(WGM22);
 

	
 
	// Do non-inverting PWM on pin OC2B (arduino pin 3) (p.159).
 
	// OC2A (arduino pin 11) stays in normal port operation:
 
	// COM2B1=1, COM2B0=0, COM2A1=0, COM2A0=0
 
	TCCR2A = (TCCR2A | _BV(COM2B1)) & ~(_BV(COM2B0) | _BV(COM2A1) | _BV(COM2A0));
 

	
 
	// No prescaler (p.162)
 
	TCCR2B = (TCCR2B & ~(_BV(CS22) | _BV(CS21))) | _BV(CS20);
 
	
 
	// Enable interrupt when TCNT2 reaches TOP (0xFF) (p.151, 163)
 
	//TIMSK2 |= _BV(TOIE2);
 
	TIMSK2 |= 0b00000001;
 

	
 
	// Initialize PORTA
 
	DDRA = 0xff;
 
	PORTA = 0x00;
 
	
 
	DDRD = 0xff;
 
	PORTD = 0xff;
 
	
 
	// todo: init radio, maybe in main
 
	
 
	sei();
 
}
 

	
 

	
 
void afsk_test() {
 
	uint8_t flap[26] = {"abcdefghijklmnopqrstuvwxyz"};
 
	afsk_send(flap, sizeof(flap)*8);
 
	afsk_start();
 
	while(afsk_busy());
 
	_delay_ms(500);
 
}
master/master/lib/led.c
Show inline comments
 
/*
 
 * led.c
 
 *
 
 * Created: 10/25/2012 3:34:03 PM
 
 *  Author: ethanzonca
 
 */ 
 
 
#include <avr/io.h>
 
 
void led_setup() {
 
	// Configure ports/pins for LEDs
 
	DDRA = 0xff;
 
	PORTA = 0x00;
 
}
 
 
void led_On(uint8_t led) {
 
	// Turn the specified LED on
 
	PORTA |= led;
 
}
 
 
void led_Off(uint8_t led) {
 
	// Turn the specified LED off
 
	PORTA &= ~(led);
 
}
 
 
void led_Toggle(uint8_t led) {
 
	// Toggle the specified LED 
 
}
 
\ No newline at end of file
master/master/lib/logger.c
Show inline comments
 
/*
 
 * CFile1.c
 
 *
 
 * Created: 11/7/2012 8:05:44 PM
 
 *  Author: mkanning
 
 */ 
 
 
#include <string.h>
 
#include <avr/pgmspace.h>
 
#include <avr/sleep.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.
 
 */
 
 
void logger_setup()
 
{
 
	while(1)
 
	{
 
		//check for SD exist/power/ready BEGIN
 
		/* setup SD card slot */
 
 
		if(!sd_raw_init()) //sd_raw.c this function may need an overhaul
 
		{
 
	#if DEBUG
 
			uart_puts_p(PSTR("MMC/SD initialization failed\n"));
 
	#endif
 
			continue;
 
			// initialization failed!!!!!!!
 
			PORTA |= 0b00000001;
 
			return;
 
		}
 
return;
 
		//check for SD exist/power/ready END
 
	
 
		//create partition BEGIN
 
		/* open first partition */ 
 
		struct partition_struct* partition = partition_open(sd_raw_read,
 
															sd_raw_read_interval,
 
	//#if SD_RAW_WRITE_SUPPORT //probably want this to be true ??
 
															sd_raw_write,
 
															sd_raw_write_interval,
 
	//#endif
 
															0
 
															);
 
		//check that partition was created correctly
 
		if(!partition)
 
		{
 
			// OH GOSH TERRIBLE ERROR HERE
 
			/* If the partition did not open, assume the storage device
 
				* is a "superfloppy", i.e. has no MBR.
 
				*/
 
			//what is MBR ??
 
			partition = partition_open(sd_raw_read,
 
										sd_raw_read_interval,
 
	#if SD_RAW_WRITE_SUPPORT //probably want this to be true ??
 
										sd_raw_write,
 
										sd_raw_write_interval,
 
	#else
 
										0,
 
										0,
 
	#endif
 
										-1
 
										);
 
			if(!partition)
 
			{
 
	#if DEBUG
 
				uart_puts_p(PSTR("opening partition failed\n"));
 
	#endif
 
				continue;
 
				// oh frick opening partition failed
 
				PORTA |= 0b00000010;
 
				return;
 
			}
 
		}
 
		//open partition END
 
	
 
	
 
		//open file system BEGIN
 
		/* open file system */
 
		struct fat_fs_struct* fs = fat_open(partition);
 
		if(!fs)
 
		{
 
			#if DEBUG
 
			uart_puts_p(PSTR("opening file system failed\n"));
 
			#endif
 
			continue;
 
			// opening fs failed!
 
			PORTA |= 0b00000100;
 
			return;
 
		}
 
		//open file system END
 
	
 
	
 
		//open directory BEGIN
 
		/* open root directory */
 
		struct fat_dir_entry_struct directory;
 
		fat_get_dir_entry_of_path(fs, "/", &directory);
 

	
 
		struct fat_dir_struct* dd = fat_open_dir(fs, &directory);
 
		if(!dd)
 
		{
 
			#if DEBUG
 
			uart_puts_p(PSTR("opening root directory failed\n"));
 
			#endif
 
			continue;
 
			// frick opening root dir failed
 
			PORTA |= 0b00000101;
 
			return;
 
		}
 
		//open directory END
 
		
 
		
 
		//simplified version of console BEGIN
 
		/* provide a simple shell */
 
		char buffer[24];
 
		while(1)
 
		{
 
			/* execute command */
 

	
 
			/* search file in current directory and open it */
 
			struct fat_file_struct* fd = open_file_in_dir(fs, dd, "data.csv"); //logger.h
 
			if(!fd)
 
			{
 
				//error open file handling
 
				continue;
 
			PORTA |= 0b00000110;
 
			return;
 
			}
 

	
 
			int32_t offset = 5;//strtolong(offset_value);
 
		int32_t offset = 0;//strtolong(offset_value);
 
			if(!fat_seek_file(fd, &offset, FAT_SEEK_SET)) //seek to begin or end or what ??
 
			{
 
				//error seek to file handling
 
				
 
			PORTA |= 0b00000111;	
 
				fat_close_file(fd);
 
				continue;
 
			return;
 
			}
 

	
 
		buffer[0] = 'H';
 
		buffer[1] = 'e';
 
		buffer[2] = 'l';
 
		buffer[3] = 'l';
 
		buffer[4] = 'o';
 
		buffer[5] = 'w';
 
		buffer[6] = 'o';
 
		buffer[7] = 'r';
 
		buffer[8] = 'l';
 
		buffer[9] = 'd';
 

	
 
			/* read text from the shell and write it to the file */
 
			uint8_t data_len = sizeof(buffer);
 
			
 
			while(1)
 
			{
 
				/* write text to file !! */
 
				if(fat_write_file(fd, (uint8_t*) buffer, data_len) != data_len)
 
				{
 
					//uart_puts_p(PSTR("error writing to file\n"));
 
					break;
 
				}
 
			}
 

	
 
			fat_close_file(fd); //may want to leave file open ??
 
		}
 
		//simplified version of console END	
 
		
 
		
 
		
 
		//prepare for closing SD connection BEGIN
 
		/* close directory */
 
		fat_close_dir(dd); //fat.c
 

	
 
		/* close file system */
 
		fat_close(fs); //fat.c
 

	
 
		/* close partition */
 
		partition_close(partition); //partition.c
 
		//prepare for closing SD connection END
 
	}
 
}	
 
 
//writes a single line to the SD card
 
uint8_t logger_writeLine(char* dateLine, uint8_t length)
 
{
 
	return length; //does not actually return length
 
}
 
 
//i think 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); //fat.h
 
}
 

	
 
//i think searches for a file
 
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/sd/sd_raw.c
Show inline comments
 
@@ -2,573 +2,587 @@
 
/*
 
 * 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);
 
           (1 << SPR10);   /* Clock Frequency: f_OSC / 128 */
 
           //(1 << SPR00); // commentnig this out means /64, which gives over 100khz as required
 
    SPSR0 &= ~(1 << SPI2X0); /* No doubled clock frequency */
 
// transmit a char
 
 while ( ! ( SPSR0 & ( 1 << SPIF0 )));  //  wait for completion of
 
 SPDR0 = 'c';                            // begin transmission
 
 
 

	
 
return;
 

	
 
    /* 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 wether 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;
 
		PORTA = 0x01;
 
    while(!(SPSR0 & (1 << SPIF0)));
 
	PORTA = 0x02;
 
    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
master/master/lib/sd/sd_raw_config.h
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.
 
 */
 

	
 
#ifndef SD_RAW_CONFIG_H
 
#define SD_RAW_CONFIG_H
 

	
 
#include <stdint.h>
 

	
 
#ifdef __cplusplus
 
extern "C"
 
{
 
#endif
 

	
 
/**
 
 * \addtogroup sd_raw
 
 *
 
 * @{
 
 */
 
/**
 
 * \file
 
 * MMC/SD support configuration (license: GPLv2 or LGPLv2.1)
 
 */
 

	
 
/**
 
 * \ingroup sd_raw_config
 
 * Controls MMC/SD write support.
 
 *
 
 * Set to 1 to enable MMC/SD write support, set to 0 to disable it.
 
 */
 
#define SD_RAW_WRITE_SUPPORT 1
 

	
 
/**
 
 * \ingroup sd_raw_config
 
 * Controls MMC/SD write buffering.
 
 *
 
 * Set to 1 to buffer write accesses, set to 0 to disable it.
 
 *
 
 * \note This option has no effect when SD_RAW_WRITE_SUPPORT is 0.
 
 */
 
#define SD_RAW_WRITE_BUFFERING 1
 

	
 
/**
 
 * \ingroup sd_raw_config
 
 * Controls MMC/SD access buffering.
 
 * 
 
 * Set to 1 to save static RAM, but be aware that you will
 
 * lose performance.
 
 *
 
 * \note When SD_RAW_WRITE_SUPPORT is 1, SD_RAW_SAVE_RAM will
 
 *       be reset to 0.
 
 */
 
#define SD_RAW_SAVE_RAM 1
 

	
 
/**
 
 * \ingroup sd_raw_config
 
 * Controls support for SDHC cards.
 
 *
 
 * Set to 1 to support so-called SDHC memory cards, i.e. SD
 
 * cards with more than 2 gigabytes of memory.
 
 */
 
#define SD_RAW_SDHC 0
 

	
 
/**
 
 * @}
 
 */
 

	
 
/* defines for customisation of sd/mmc port access */
 
#if defined(__AVR_ATmega8__) || \
 
    defined(__AVR_ATmega48__) || \
 
    defined(__AVR_ATmega48P__) || \
 
    defined(__AVR_ATmega88__) || \
 
    defined(__AVR_ATmega88P__) || \
 
    defined(__AVR_ATmega168__) || \
 
    defined(__AVR_ATmega168P__) || \
 
    defined(__AVR_ATmega328P__)
 
    #define configure_pin_mosi() DDRB |= (1 << DDB3)
 
    #define configure_pin_sck() DDRB |= (1 << DDB5)
 
    #define configure_pin_ss() DDRB |= (1 << DDB2)
 
    #define configure_pin_miso() DDRB &= ~(1 << DDB4)
 

	
 
    #define select_card() PORTB &= ~(1 << PORTB2)
 
    #define unselect_card() PORTB |= (1 << PORTB2)
 
#elif defined(__AVR_ATmega16__) || \
 
      defined(__AVR_ATmega32__)
 
    #define configure_pin_mosi() DDRB |= (1 << DDB5)
 
    #define configure_pin_sck() DDRB |= (1 << DDB7)
 
    #define configure_pin_ss() DDRB |= (1 << DDB4)
 
    #define configure_pin_miso() DDRB &= ~(1 << DDB6)
 

	
 
    #define select_card() PORTB &= ~(1 << PORTB4)
 
    #define unselect_card() PORTB |= (1 << PORTB4)
 
#elif defined(__AVR_ATmega64__) || \
 
      defined(__AVR_ATmega128__) || \
 
      defined(__AVR_ATmega169__)
 
    #define configure_pin_mosi() DDRB |= (1 << DDB2)
 
    #define configure_pin_sck() DDRB |= (1 << DDB1)
 
    #define configure_pin_ss() DDRB |= (1 << DDB0)
 
    #define configure_pin_miso() DDRB &= ~(1 << DDB3)
 

	
 
    #define select_card() PORTB &= ~(1 << PORTB0)
 
    #define unselect_card() PORTB |= (1 << PORTB0)
 
#elif defined(__AVR_ATmega164P__) || \
 
	  defined(__AVR_ATmega324P__) || \
 
	  defined(__AVR_ATmega664P__)
 
    #define configure_pin_mosi() DDRB |= (1 << DDRB5) //PB5
 
    #define configure_pin_sck() DDRB |= (1 << DDRB7) //PB7
 
    #define configure_pin_ss() DDRB |= (1 << DDRB0) //PB0 - custom pin
 
    #define configure_pin_miso() DDRB &= ~(1 << DDRB6) //PB6
 
	
 
    #define select_card() PORTB &= ~(1 << PORTB0)
 
    #define unselect_card() PORTB |= (1 << PORTB0)
 
#else
 
    #error "no sd/mmc pin mapping available!" //sends error if micro not specified
 
#endif
 

	
 

	
 

	
 
#define configure_pin_available() DDRC &= ~(1 << DDRC4)
 
#define configure_pin_locked() DDRC &= ~(1 << DDRC5)
 

	
 
#define get_pin_available() (PINC & (1 << PINC4))
 
#define get_pin_locked() (PINC & (1 << PINC5))
 

	
 

	
 

	
 
#if SD_RAW_SDHC
 
    typedef uint64_t offset_t;
 
#else
 
    typedef uint32_t offset_t;
 
#endif
 

	
 

	
 

	
 
/* configuration checks */
 
#if SD_RAW_WRITE_SUPPORT
 
#undef SD_RAW_SAVE_RAM
 
#define SD_RAW_SAVE_RAM 0
 
#else
 
#undef SD_RAW_WRITE_BUFFERING
 
#define SD_RAW_WRITE_BUFFERING 0
 
#endif
 

	
 
#ifdef __cplusplus
 
}
 
#endif
 

	
 
#endif
 

	
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 "lib/serial.h"
 
#include "lib/aprs.h"
 
#include "lib/afsk.h"
 
#include "lib/led.h"
 
#include "lib/logger.h"
 

	
 
#include "lib/sd/sd_raw_config.h"
 

	
 
void micro_setup() {
 
	// Generic microcontroller config options
 
	
 
}
 

	
 
int main(void)
 
{
 
	// Initialize
 
	micro_setup();
 
	led_setup();
 

	
 

	
 
	serial_setup(); // Config serial ports
 
	afsk_setup();
 
	
 
	_delay_ms(400);	
 
	_delay_ms(400);	
 
	
 
	logger_setup();
 
	
 
    while(1)
 
    {
 
		//afsk_test();
 
		aprs_send();
 
		_delay_ms(400);
 
		_delay_ms(400);
 
		//aprs_send();
 

	
 
		_delay_ms(400);
 
		_delay_ms(400);
 
		_delay_ms(400);
 
		_delay_ms(400);
 
        serial_SendCommand('0','A',0,0);
 
        //serial_SendCommand('0','A',0,0);
 
		
 
		
 
    }
 
}
 
\ No newline at end of file
0 comments (0 inline, 0 general)