//************************************************************************************
//**  
//**  File name:     C:\Documents and Settings\Henry Bergin\Desktop\Flowcode 5 project files\Misc\two files\multifiles1.c
//**  Title:         
//**  Description:   
//**  
//**  Generated by:  Flowcode v5.3.0.0
//**  Date:          Friday, September 14, 2012 19:33:11
//**  Licence:       Professional
//**  Registered to: tackyattack
//**  Licence key:   K38B95
//**  
//**  
//**  http://www.matrixmultimedia.com
//**  
//************************************************************************************


#define MX_AVR

#define MX_USES_UINT8 1
#define MX_USES_SINT16 0
#define MX_USES_CHAR 0
#define MX_USES_FLOAT 0
#define MX_USES_SINT32 0
#define MX_USES_BOOL 1
#define MX_USES_UINT16 0
#define MX_USES_UINT32 0
//Defines for microcontroller
#define FC_CAL_AVR
#define MX_ADC
#define MX_ADC_TYPE_2
#define MX_ADC_BITS_10
#define MX_EE
#define MX_EE_SIZE 1024
#define MX_SPI_1
#define MX_SPI_1_MISO_PORT PORTB
#define MX_SPI_1_MISO_TRIS DDRB
#define MX_SPI_1_MISO_PIN 4
#define MX_SPI_1_MOSI_PORT PORTB
#define MX_SPI_1_MOSI_TRIS DDRB
#define MX_SPI_1_MOSI_PIN 3
#define MX_SPI_1_CLK_PORT PORTB
#define MX_SPI_1_CLK_TRIS DDRB
#define MX_SPI_1_CLK_PIN 5
#define MX_SPI_1_SS_PORT PORTB
#define MX_SPI_1_SS_TRIS DDRB
#define MX_SPI_1_SS_PIN 2
#define MX_UART_1
#define MX_UART_1_TX_PORT PORTD
#define MX_UART_1_TX_TRIS DDRD
#define MX_UART_1_TX_PIN 1
#define MX_UART_1_RX_PORT PORTD
#define MX_UART_1_RX_TRIS DDRD
#define MX_UART_1_RX_PIN 0
#define MX_UART_ID
#define MX_UART_UCSRC
#define MX_MI2C
#define MX_I2C_1
#define MX_I2C_1_SDA_PORT PORTC
#define MX_I2C_1_SDA_TRIS DDRC
#define MX_I2C_1_SDA_PIN 4
#define MX_I2C_1_SCL_PORT PORTC
#define MX_I2C_1_SCL_TRIS DDRC
#define MX_I2C_1_SCL_PIN 5
#define MX_PWM
#define MX_PWMTYPE 1
#define MX_PWM_CNT 6
#define MX_PWM_TMR0_CNT 2
#define MX_PWM_TMR1_CNT 2
#define MX_PWM_TMR2_CNT 2
#define MX_PWM_PSCA1
#define MX_PWM_PSCA8
#define MX_PWM_PSCA64
#define MX_PWM_PSCA256
#define MX_PWM_PSCA1024
#define MX_PWM_1_PORT PORTD
#define MX_PWM_1_TRIS DDRD
#define MX_PWM_1_PIN 6
#define MX_PWM_2_PORT PORTD
#define MX_PWM_2_TRIS DDRD
#define MX_PWM_2_PIN 5
#define MX_PWM_3_PORT PORTB
#define MX_PWM_3_TRIS DDRB
#define MX_PWM_3_PIN 1
#define MX_PWM_4_PORT PORTB
#define MX_PWM_4_TRIS DDRB
#define MX_PWM_4_PIN 2
#define MX_PWM_5_PORT PORTB
#define MX_PWM_5_TRIS DDRB
#define MX_PWM_5_PIN 3
#define MX_PWM_6_PORT PORTD
#define MX_PWM_6_TRIS DDRD
#define MX_PWM_6_PIN 3

//Functions
#define F_CPU 20000000UL
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <avr\io.h>
#include <avr\interrupt.h>
#include <avr\eeprom.h>
#include <avr\wdt.h>

//Configuration data
#pragma DATA 0x0, 0xdf
#pragma DATA 0x1, 0xff
#pragma DATA 0x2, 0xff

//Internal functions
#include "C:\Program Files\Flowcode(AVR)\v5\FCD\internals.c"

//Macro function declarations


//Variable declarations
#define FCV_TRUE (1)
#define FCV_FALSE (0)
volatile MX_UINT8 FCV_VALUE;




//FAT16(0): //Defines:

/**** Macro Substitutions ****
a = Unique Ref
b = SPI Channel
c = MOSI Pin
d = MOSI Port
e = MISO Pin
f = MISO Port
g = SCK Pin
h = SCK Port
i = CS Pin
j = CS Port
k = File Creation Time
l = File Creation Date
m = FAT System Type - 0=FAT16 Only / 1=FAT32 Only / 2=FAT16&32
******************************/


//Definitions for CS control line
#define FAT_1_MX_SPI_FAT_CS_PIN		2
#define FAT_1_MX_SPI_FAT_CS_PORT		portb
#define FAT_1_MX_SPI_FAT_CS_TRIS		trisb


//Definitions for SPI slot allocation
#ifndef	MX_SPI_REF1
	#define MX_SPI_REF1
	#define FAT_1_MX_SPI_UREF			1
	#define MX_SPI_CHANNEL_1		1
	#define MX_SPI_MOSI_PIN_1		-1
	#define MX_SPI_MOSI_PORT_1		port0
	#define MX_SPI_MOSI_TRIS_1		tris0
	#define MX_SPI_MISO_PIN_1		-1
	#define MX_SPI_MISO_PORT_1		port0
	#define MX_SPI_MISO_TRIS_1		tris0
	#define MX_SPI_SCK_PIN_1		-1
	#define MX_SPI_SCK_PORT_1		port0
	#define MX_SPI_SCK_TRIS_1		tris0
	#define MX_SPI_CS_PIN_1			0
	#define MX_SPI_CS_PORT_1		0
	#define MX_SPI_BMODE_1			1
	#define MX_SPI_PR_SCALE_1		16
	#define MX_SPI_PO_SCALE_1		1
	#define MX_SPI_INT_1			0
#else
 #ifndef	MX_SPI_REF2
	#define MX_SPI_REF2
	#define FAT_1_MX_SPI_UREF			2
	#define MX_SPI_CHANNEL_2		1
	#define MX_SPI_MOSI_PIN_2		-1
	#define MX_SPI_MOSI_PORT_2		port0
	#define MX_SPI_MOSI_TRIS_2		tris0
	#define MX_SPI_MISO_PIN_2		-1
	#define MX_SPI_MISO_PORT_2		port0
	#define MX_SPI_MISO_TRIS_2		tris0
	#define MX_SPI_SCK_PIN_2		-1
	#define MX_SPI_SCK_PORT_2		port0
	#define MX_SPI_SCK_TRIS_2		tris0
	#define MX_SPI_CS_PIN_2			0
	#define MX_SPI_CS_PORT_2		0
	#define MX_SPI_BMODE_2			1
	#define MX_SPI_PR_SCALE_2		16
	#define MX_SPI_PO_SCALE_2		1
	#define MX_SPI_INT_2			0
 #else
  #ifndef	MX_SPI_REF3
	#define MX_SPI_REF3
	#define FAT_1_MX_SPI_UREF			3
	#define MX_SPI_CHANNEL_3		1
	#define MX_SPI_MOSI_PIN_3		-1
	#define MX_SPI_MOSI_PORT_3		port0
	#define MX_SPI_MOSI_TRIS_3		tris0
	#define MX_SPI_MISO_PIN_3		-1
	#define MX_SPI_MISO_PORT_3		port0
	#define MX_SPI_MISO_TRIS_3		tris0
	#define MX_SPI_SCK_PIN_3		-1
	#define MX_SPI_SCK_PORT_3		port0
	#define MX_SPI_SCK_TRIS_3		tris0
	#define MX_SPI_CS_PIN_3			0
	#define MX_SPI_CS_PORT_3		0
	#define MX_SPI_BMODE_3			1
	#define MX_SPI_PR_SCALE_3		16
	#define MX_SPI_PO_SCALE_3		1
	#define MX_SPI_INT_3			0
  #else
   #ifndef	MX_SPI_REF4
	#define MX_SPI_REF4
	#define FAT_1_MX_SPI_UREF			4
	#define MX_SPI_CHANNEL_4		1
	#define MX_SPI_MOSI_PIN_4		-1
	#define MX_SPI_MOSI_PORT_4		port0
	#define MX_SPI_MOSI_TRIS_4		tris0
	#define MX_SPI_MISO_PIN_4		-1
	#define MX_SPI_MISO_PORT_4		port0
	#define MX_SPI_MISO_TRIS_4		tris0
	#define MX_SPI_SCK_PIN_4		-1
	#define MX_SPI_SCK_PORT_4		port0
	#define MX_SPI_SCK_TRIS_4		tris0
	#define MX_SPI_CS_PIN_4			0
	#define MX_SPI_CS_PORT_4		0
	#define MX_SPI_BMODE_4			1
	#define MX_SPI_PR_SCALE_4		16
	#define MX_SPI_PO_SCALE_4		1
	#define MX_SPI_INT_4			0
   #endif
  #endif
 #endif
#endif

#define FAT_1_SPI_Master_Init		CAL_APPEND(FC_CAL_SPI_Master_Init_, FAT_1_MX_SPI_UREF)
#define FAT_1_SPI_Master_Uninit	CAL_APPEND(FC_CAL_SPI_Master_Uninit_, FAT_1_MX_SPI_UREF)
#define FAT_1_SPI_Master_Byte		CAL_APPEND(FC_CAL_SPI_Master_Byte_, FAT_1_MX_SPI_UREF)
#define FAT_1_SPI_Set_Prescaler	CAL_APPEND(FC_CAL_SPI_Set_Prescaler_, FAT_1_MX_SPI_UREF)

extern void FAT_1_SPI_Master_Init ();
extern void FAT_1_SPI_Master_Uninit ();
extern MX_UINT8 FAT_1_SPI_Master_Byte (MX_UINT8 DataOut);
extern void FAT_1_SPI_Set_Prescaler (MX_UINT8 Prescaler);

//Flowcode Defines
#define FAT_1_FILE_CREATEDATE		0
#define FAT_1_FILE_CREATETIME		-1007479
#define FAT_1_FAT_TYPE				0		//0-FAT16(FAT) / 1-FAT32 / 2-FAT16&32

//!!EDIT HERE TO CHANGE MAX NO OF FILES!!
#define FAT_1_CONCURRENT_FILES		2		//%n

#include <string.h>

//SD commands, many of these are not used here
#ifndef	MX_FAT_COMMANDS
	#define	MX_FAT_COMMANDS
	#define GO_IDLE_STATE            0
	#define SEND_OP_COND             1
	#define SEND_IF_COND			 8
	#define SEND_CSD                 9
	#define STOP_TRANSMISSION        12
	#define SEND_STATUS              13
	#define SET_BLOCK_LEN            16
	#define READ_SINGLE_BLOCK        17
	#define READ_MULTIPLE_BLOCKS     18
	#define WRITE_SINGLE_BLOCK       24
	#define WRITE_MULTIPLE_BLOCKS    25
	#define ERASE_BLOCK_START_ADDR   32
	#define ERASE_BLOCK_END_ADDR     33
	#define ERASE_SELECTED_BLOCKS    38
	#define SD_SEND_OP_COND			 41   //ACMD
	#define APP_CMD					 55
	#define READ_OCR				 58
	#define CRC_ON_OFF               59
#endif


#ifndef	MX_FAT_ERR_FLAGS
	#define MX_FAT_ERR_FLAGS

	//Common Defines
	#define MX_ERR_NOCARD			0xFF
	#define MX_ERR_NORESP			0xFE
	#define MX_ERR_NOACK			0xFD
	#define MX_ERR_TOUT				0xFC
	#define MX_ERR_RESERVED			0xFB
	#define MX_ERR_BAD				0xFA
	#define MX_ERR_FREE				0xF0
	#define MX_ERR_FILENOTFOUND		0xEF
	#define MX_ERR_ROOTFULL			0xEE
	#define MX_ERR_SECTBYTES		0xED
	#define MX_ACK_FILEEMPTY		0x03
	#define MX_ACK_FILETYPE			0x02
	#define MX_ACK_EOF				0x01
	#define MX_ACK_OK				0x00
#endif

//Global Variables
MX_UINT8 FAT_1_mx_card_bufferl[256];		//512-Byte Global Buffer Variables
MX_UINT8 FAT_1_mx_card_bufferh[256];
MX_UINT8 FAT_1_mx_name_ext[12];			//11 byte fat file name: 8 MX_UINT8 filename + 3 MX_UINT8 extension

//Card Specific Variables
MX_UINT8 FAT_1_mx_sects_per_clust;			//Number of sectors per cluster    - Added BR 06/10
MX_UINT8 FAT_1_mx_sdhc_flag = 0;			//Standard / SDHC mode
MX_UINT8 FAT_1_mx_card_type;
MX_UINT16 FAT_1_mx_root_sectors = 0;		//Number of sectors in the root directory
MX_UINT16 FAT_1_mx_fat_size = 0;			//FAT size in sectors
MX_UINT32 FAT_1_mx_fat_start = 0;			//Start address of FAT tables
MX_UINT32 FAT_1_mx_root_start = 0;			//Start address of root directory
MX_UINT32 FAT_1_mx_data_start = 0;			//Start address of the data

//File Specific Variables
MX_UINT8 FAT_1_mx_file_entry[FAT_1_CONCURRENT_FILES];			//Directory entry of file
MX_UINT32 FAT_1_mx_file_size[FAT_1_CONCURRENT_FILES];			//Size of file in bytes
MX_UINT32 FAT_1_mx_file_address[FAT_1_CONCURRENT_FILES]; 		//Start address of File
MX_UINT32 FAT_1_mx_file_pointer[FAT_1_CONCURRENT_FILES];		//Current address loaded in memory
MX_UINT32 FAT_1_mx_file_sector[FAT_1_CONCURRENT_FILES];		//Current sector of file
MX_UINT32 FAT_1_mx_folder_size[FAT_1_CONCURRENT_FILES];		//Folder size in sectors
MX_UINT32 FAT_1_mx_folder_start[FAT_1_CONCURRENT_FILES];		//Start address of Folder
MX_UINT8 FAT_1_mx_file_idx = 0;

//FAT Specific Variables
#if (FAT_1_FAT_TYPE == 0)
	MX_UINT16 FAT_1_mx_cluster = 2;		//Current data FAT_1_mx_cluster in the memory
	#define FAT_1_SECT_ADDR_LEN			2
	#define FAT_1_FATS_PER_SECT			(512 / 2)	//2 bytes per fat record
	#define FAT_1_NOT_ADDRESS_MARKER		0xFFF0
	#define FAT_1_MX_EOF_MARKER			0xFFF7
#endif
#if (FAT_1_FAT_TYPE == 1)
	MX_UINT32 FAT_1_mx_cluster = 2;		//Current data FAT_1_mx_cluster in the memory
	#define FAT_1_mx_fat_system  			1
	#define FAT_1_SECT_ADDR_LEN			4
	#define FAT_1_FATS_PER_SECT			(512 / 4)	//4 bytes per fat record
	#define FAT_1_NOT_ADDRESS_MARKER		0x0FFFFFF0
	#define FAT_1_MX_EOF_MARKER			0x0FFFFFF7
#endif
#if (FAT_1_FAT_TYPE == 2)
	MX_UINT32 FAT_1_mx_cluster = 2;		//Current data FAT_1_mx_cluster in the memory
	MX_UINT8 FAT_1_mx_fat_system;			//Type of FAT file system in use on disk     - Added BR 07/10
	MX_UINT8 FAT_1_SECT_ADDR_LEN;			//Defines become variables
	MX_UINT16 FAT_1_FATS_PER_SECT;
	MX_UINT32 FAT_1_NOT_ADDRESS_MARKER;
	MX_UINT32 FAT_1_MX_EOF_MARKER;
#endif




//FAT16(0): //Macro function declarations

static MX_UINT8 FCD_FAT160_Init_FAT();
static MX_UINT8 FCD_FAT160_Open_File(MX_STRING File_Name, MX_UINT8 MSZ_File_Name);
static MX_UINT8 FCD_FAT160_Read_File_Sector();
static MX_SINT16 FCD_FAT160_Read_File_Length();
static MX_UINT8 FCD_FAT160_Move_To_Next_File_Sector(MX_UINT8 Force_Next_Sector);
static MX_UINT8 FCD_FAT160_Append_String_To_File(MX_STRING String, MX_UINT8 MSZ_String);
static MX_UINT8 FCD_FAT160_Write_File_Sector();
static MX_UINT8 FCD_FAT160_Create_File(MX_STRING File_Name, MX_UINT8 MSZ_File_Name);
static MX_UINT8 FCD_FAT160_Delete_File(MX_STRING File_Name, MX_UINT8 MSZ_File_Name);
static void FCD_FAT160_Write_Byte_To_Buffer(MX_SINT16 Address, MX_UINT8 Data);
static MX_UINT8 FCD_FAT160_Read_Byte_From_Buffer(MX_SINT16 Address);
static MX_UINT8 FCD_FAT160_Open_Folder(MX_STRING Folder_Name, MX_UINT8 MSZ_Folder_Name);
static MX_SINT16 FCD_FAT160_Scan_Current_Folder(MX_SINT16 Current_Idx, MX_UINT8 Scan_Type);
static MX_UINT8 FCD_FAT160_Read_Byte_From_Scan(MX_UINT8 idx);
static MX_UINT8 FCD_FAT160_MX_Init_Card();
static MX_UINT8 FCD_FAT160_MX_Send_Buffer(long address);
static MX_UINT8 FCD_FAT160_MX_Get_Buffer(long address);
static void FCD_FAT160_MX_Format_File_String(MX_STRING File_Name, MX_UINT8 MSZ_File_Name);
static void FCD_FAT160_MX_Add_Sector_To_File();
static void FCD_FAT160_MX_Clear_Buffer();
static MX_UINT8 FCD_FAT160_Read_Next_File_Sector();
static MX_UINT8 FCD_FAT160_MX_Send_Cmd(MX_UINT8 Cmd, MX_UINT32 Addr);
static void FCD_FAT160_Set_File_Index(MX_UINT8 File_Index);



//FAT16(0): //Macro implementations


static MX_UINT8 FCD_FAT160_Init_FAT()
{
	
		MX_UINT8 retval;
		MX_UINT8 i, num_fats;
		MX_UINT16 bytes_per_sect = 0;
		MX_UINT16 reserved_sectors;
		MX_UINT32 partition_start = 0;  //Start address of the partition
		MX_UINT32 root_size; 			//Number of 32 byte root entries.
		MX_Union32 Temp32;
		MX_Union16 Temp16;

		retval = FCD_FAT160_MX_Init_Card(); 	//Startup Card
		if (retval)
		{
			FAT_1_SPI_Set_Prescaler(2);	//Try again at a lower speed 1:64

			retval = FCD_FAT160_MX_Init_Card(); 	//Read Master Boot Record if available

			if (retval)
				return(retval); 		//Startup error or no card
		}

		delay_ms(50);

		retval = FCD_FAT160_MX_Get_Buffer(0); 	//Read Master Boot Record if available

		if (retval)
			return MX_ERR_SECTBYTES;

		i = FCD_FAT160_Read_Byte_From_Buffer(0);

		if(i!=0xE9 && i!=0xEB)
		{
			Temp16.AsByte[0] = FCD_FAT160_Read_Byte_From_Buffer(510);
			Temp16.AsByte[1] = FCD_FAT160_Read_Byte_From_Buffer(511);

			if (Temp16.AsInt != 0xaa55)
				return MX_ERR_SECTBYTES;

			Temp32.AsByte[0] = FCD_FAT160_Read_Byte_From_Buffer(454);
			Temp32.AsByte[1] = FCD_FAT160_Read_Byte_From_Buffer(455);
			Temp32.AsByte[2] = FCD_FAT160_Read_Byte_From_Buffer(456);
			Temp32.AsByte[3] = FCD_FAT160_Read_Byte_From_Buffer(457);
			partition_start = Temp32.AsLong;

			FCD_FAT160_MX_Get_Buffer(partition_start);

			i = FCD_FAT160_Read_Byte_From_Buffer(0);

			if (i!=0xE9 && i!=0xEB)
				return MX_ERR_SECTBYTES;
		}


		Temp16.AsByte[0] = FCD_FAT160_Read_Byte_From_Buffer(0x0B); //Bytes per sector - normally 512
		Temp16.AsByte[1] = FCD_FAT160_Read_Byte_From_Buffer(0x0C);
		bytes_per_sect = Temp16.AsInt;

		if (bytes_per_sect != 512)
			return MX_ERR_SECTBYTES;

		FAT_1_mx_sects_per_clust = FCD_FAT160_Read_Byte_From_Buffer(0x0D);								//Read number of sectors per FAT_1_mx_cluster

		Temp16.AsByte[0] = FCD_FAT160_Read_Byte_From_Buffer(0x0E);										//Number of reserved sectors
		Temp16.AsByte[1] = FCD_FAT160_Read_Byte_From_Buffer(0x0F);
		reserved_sectors = Temp16.AsInt;

		num_fats = FCD_FAT160_Read_Byte_From_Buffer(0x10);											//Num of copies of FAT - normally 2

		#if (FAT_1_FAT_TYPE == 2)
			if ( FCD_FAT160_Read_Byte_From_Buffer(0x55) == '3')									//Is this a FAT32 card?
			{
				FAT_1_mx_fat_system = 1;
				FAT_1_SECT_ADDR_LEN = 4;
				FAT_1_FATS_PER_SECT = 128;
				FAT_1_NOT_ADDRESS_MARKER = 0x0FFFFFF0;
				FAT_1_MX_EOF_MARKER = 0x0FFFFFF7;
			}
			else
			{
				FAT_1_mx_fat_system = 0;
				FAT_1_SECT_ADDR_LEN = 2;
				FAT_1_FATS_PER_SECT = 256;
				FAT_1_NOT_ADDRESS_MARKER = 0xFFF0;
				FAT_1_MX_EOF_MARKER = 0xFFF7;
			}
		#endif

		FAT_1_mx_fat_start = partition_start + reserved_sectors;									//start of FAT address space in sectors


		#if (FAT_1_FAT_TYPE == 0)																//FAT32 uses normal folder cluster for root

			Temp16.AsByte[0] = FCD_FAT160_Read_Byte_From_Buffer(0x11);										//Size of root directory x 32 byte file/directory entries
			Temp16.AsByte[1] = FCD_FAT160_Read_Byte_From_Buffer(0x12);
			root_size = Temp16.AsInt;

			if(root_size == 0)																//if root size not defined here
			{
				Temp32.AsByte[0] = FCD_FAT160_Read_Byte_From_Buffer(0x24);									//Size of root directory x 32 byte file/directory entries
				Temp32.AsByte[1] = FCD_FAT160_Read_Byte_From_Buffer(0x25);
				Temp32.AsByte[2] = FCD_FAT160_Read_Byte_From_Buffer(0x26);
				Temp32.AsByte[3] = FCD_FAT160_Read_Byte_From_Buffer(0x27);
				root_size = Temp32.AsLong;
			}
			FAT_1_mx_root_sectors = root_size >> 4;												//Number of sectors in the root directory

			Temp16.AsByte[0] = FCD_FAT160_Read_Byte_From_Buffer(0x16);										//FAT size in sectors
			Temp16.AsByte[1] = FCD_FAT160_Read_Byte_From_Buffer(0x17);
			FAT_1_mx_fat_size = Temp16.AsInt;

			FAT_1_mx_root_start = FAT_1_mx_fat_start + (num_fats * FAT_1_mx_fat_size);						//start of the root directory in sectors
			FAT_1_mx_data_start = FAT_1_mx_root_start + FAT_1_mx_root_sectors;								//start of the data FAT_1_mx_clusters in sectors

		#endif
		#if (FAT_1_FAT_TYPE == 1)																//FAT32 uses normal folder cluster for root

			FAT_1_mx_root_sectors = FAT_1_mx_sects_per_clust;

			Temp32.AsByte[0] = FCD_FAT160_Read_Byte_From_Buffer(0x24);											//FAT size in sectors
			Temp32.AsByte[1] = FCD_FAT160_Read_Byte_From_Buffer(0x25);
			Temp32.AsByte[2] = FCD_FAT160_Read_Byte_From_Buffer(0x26);
			Temp32.AsByte[3] = FCD_FAT160_Read_Byte_From_Buffer(0x27);
			FAT_1_mx_fat_size = Temp32.AsLong;

			Temp32.AsByte[0] = FCD_FAT160_Read_Byte_From_Buffer(0x2C);										//first cluster address of root directory
			Temp32.AsByte[1] = FCD_FAT160_Read_Byte_From_Buffer(0x2D);
			Temp32.AsByte[2] = FCD_FAT160_Read_Byte_From_Buffer(0x2E);
			Temp32.AsByte[3] = FCD_FAT160_Read_Byte_From_Buffer(0x2F);
			root_size = Temp32.AsLong;

			FAT_1_mx_data_start = FAT_1_mx_fat_start + (num_fats * FAT_1_mx_fat_size);						//start of the root directory in sectors
			FAT_1_mx_root_start = FAT_1_mx_data_start + ((root_size - 2) * FAT_1_mx_sects_per_clust);			//Move to sector containing start of file

		#endif
		#if (FAT_1_FAT_TYPE == 2)
			if (FAT_1_mx_fat_system == 0)																//FAT32 uses normal folder cluster for root
			{
				Temp16.AsByte[0] = FCD_FAT160_Read_Byte_From_Buffer(0x11);										//Size of root directory x 32 byte file/directory entries
				Temp16.AsByte[1] = FCD_FAT160_Read_Byte_From_Buffer(0x12);
				root_size = Temp16.AsInt;

				if(root_size == 0)																//if root size not defined here
				{
					Temp32.AsByte[0] = FCD_FAT160_Read_Byte_From_Buffer(0x24);									//Size of root directory x 32 byte file/directory entries
					Temp32.AsByte[1] = FCD_FAT160_Read_Byte_From_Buffer(0x25);
					Temp32.AsByte[2] = FCD_FAT160_Read_Byte_From_Buffer(0x26);
					Temp32.AsByte[3] = FCD_FAT160_Read_Byte_From_Buffer(0x27);
					root_size = Temp32.AsLong;
				}
				FAT_1_mx_root_sectors = root_size >> 4;												//Number of sectors in the root directory

				Temp16.AsByte[0] = FCD_FAT160_Read_Byte_From_Buffer(0x16);										//FAT size in sectors
				Temp16.AsByte[1] = FCD_FAT160_Read_Byte_From_Buffer(0x17);
				FAT_1_mx_fat_size = Temp16.AsInt;

				FAT_1_mx_root_start = FAT_1_mx_fat_start + (num_fats * FAT_1_mx_fat_size);						//start of the root directory in sectors
				FAT_1_mx_data_start = FAT_1_mx_root_start + FAT_1_mx_root_sectors;								//start of the data FAT_1_mx_clusters in sectors

			}
			if (FAT_1_mx_fat_system == 1)																//FAT32 uses normal folder cluster for root
			{
				FAT_1_mx_root_sectors = FAT_1_mx_sects_per_clust;

				Temp32.AsByte[0] = FCD_FAT160_Read_Byte_From_Buffer(0x24);										//FAT size in sectors
				Temp32.AsByte[1] = FCD_FAT160_Read_Byte_From_Buffer(0x25);
				Temp32.AsByte[2] = FCD_FAT160_Read_Byte_From_Buffer(0x26);
				Temp32.AsByte[3] = FCD_FAT160_Read_Byte_From_Buffer(0x27);
				FAT_1_mx_fat_size = Temp32.AsLong;

				Temp32.AsByte[0] = FCD_FAT160_Read_Byte_From_Buffer(0x2C);										//first cluster address of root directory
				Temp32.AsByte[1] = FCD_FAT160_Read_Byte_From_Buffer(0x2D);
				Temp32.AsByte[2] = FCD_FAT160_Read_Byte_From_Buffer(0x2E);
				Temp32.AsByte[3] = FCD_FAT160_Read_Byte_From_Buffer(0x2F);
				root_size = Temp32.AsLong;

				FAT_1_mx_data_start = FAT_1_mx_fat_start + (num_fats * FAT_1_mx_fat_size);						//start of the root directory in sectors
				FAT_1_mx_root_start = FAT_1_mx_data_start + ((root_size - 2) * FAT_1_mx_sects_per_clust);			//Move to sector containing start of file
			}
		#endif

		for (i = 0; i < FAT_1_CONCURRENT_FILES; i++)													//Init all file folders to root
		{
			FAT_1_mx_folder_size[i] = FAT_1_mx_root_sectors;
			FAT_1_mx_folder_start[i] = FAT_1_mx_root_start;
		}

		return retval;

}

static MX_UINT8 FCD_FAT160_Open_File(MX_STRING File_Name, MX_UINT8 MSZ_File_Name)
{
	
		MX_UINT8 i;
		MX_UINT8 name_comp[11];
		MX_UINT16 idx_fat;
		MX_UINT16 Idx;

		#if (FAT_1_FAT_TYPE == 0)
			MX_UINT16 fat_pointer = 0xFFFF;
		#endif
		#if (FAT_1_FAT_TYPE == 1)
			MX_UINT32 fat_pointer = 0x0FFFFFFF;
		#endif
		#if (FAT_1_FAT_TYPE == 2)
			MX_UINT32 fat_pointer;
			if (FAT_1_mx_fat_system == 0)
				fat_pointer = 0xFFFF;
			else fat_pointer = 0x0FFFFFFF;
		#endif
		MX_UINT32 fat_address;

		MX_Union32 Temp32;

		FCD_FAT160_MX_Format_File_String(File_Name, MSZ_File_Name);						//Convert filename to 8.3 format

		FAT_1_mx_file_pointer[FAT_1_mx_file_idx] = FAT_1_mx_folder_start[FAT_1_mx_file_idx];								//Move to start of root
		while (FAT_1_mx_file_pointer[FAT_1_mx_file_idx] < (FAT_1_mx_folder_start[FAT_1_mx_file_idx] + FAT_1_mx_folder_size[FAT_1_mx_file_idx]))
		{
			FCD_FAT160_MX_Get_Buffer(FAT_1_mx_file_pointer[FAT_1_mx_file_idx]);								//Read sector of root directory
			for(i=0;i<16;i++)													//16 file or directory references per sector
			{
				Idx = i << 5;

				name_comp[0] = FCD_FAT160_Read_Byte_From_Buffer(0 + Idx);					//Move DOS 8.3 Filename into 2nd comparison buffer
				name_comp[1] = FCD_FAT160_Read_Byte_From_Buffer(1 + Idx);
				name_comp[2] = FCD_FAT160_Read_Byte_From_Buffer(2 + Idx);
				name_comp[3] = FCD_FAT160_Read_Byte_From_Buffer(3 + Idx);
				name_comp[4] = FCD_FAT160_Read_Byte_From_Buffer(4 + Idx);
				name_comp[5] = FCD_FAT160_Read_Byte_From_Buffer(5 + Idx);
				name_comp[6] = FCD_FAT160_Read_Byte_From_Buffer(6 + Idx);
				name_comp[7] = FCD_FAT160_Read_Byte_From_Buffer(7 + Idx);
				name_comp[8] = FCD_FAT160_Read_Byte_From_Buffer(8 + Idx);
				name_comp[9] = FCD_FAT160_Read_Byte_From_Buffer(9 + Idx);
				name_comp[10] = FCD_FAT160_Read_Byte_From_Buffer(10 + Idx);

				/*
				//Debug Information
				if(name_comp[0] > 'A')
				{
					FCD_LCDDisplay0_Clear();
					FCD_LCDDisplay0_PrintString(FAT_1_mx_name_ext, 11);
					FCD_LCDDisplay0_Cursor(0,1);
					FCD_LCDDisplay0_PrintString(name_comp, 11);
					FCD_LCDDisplay0_Cursor(13,1);
					FCD_LCDDisplay0_PrintNumber(FCI_COMPARE(FAT_1_mx_name_ext,11,name_comp,11,1));
					delay_s(2);
				}*/

				if (FCI_COMPARE(FAT_1_mx_name_ext,11,name_comp,11,1) == 0)			//Perform filename comparison
				{
					FAT_1_mx_file_entry[FAT_1_mx_file_idx] = i;										//Store file address
					FAT_1_mx_file_address[FAT_1_mx_file_idx] = FAT_1_mx_file_pointer[FAT_1_mx_file_idx];
					FAT_1_mx_file_sector[FAT_1_mx_file_idx] = 1;

					Temp32.AsByte[0] = FCD_FAT160_Read_Byte_From_Buffer(26 + Idx);			//Read Cluster of data start
					Temp32.AsByte[1] = FCD_FAT160_Read_Byte_From_Buffer(27 + Idx);
					Temp32.AsByte[2] = 0;
					Temp32.AsByte[3] = 0;

					#if (FAT_1_FAT_TYPE == 1 || FAT_1_FAT_TYPE == 2)
						if(FAT_1_mx_fat_system == 1)
						{
							Temp32.AsByte[2] = FCD_FAT160_Read_Byte_From_Buffer(20 + Idx);
							Temp32.AsByte[3] = FCD_FAT160_Read_Byte_From_Buffer(21 + Idx);
						}
					#endif

					FAT_1_mx_cluster = Temp32.AsLong;

					Temp32.AsByte[0] = FCD_FAT160_Read_Byte_From_Buffer(28 + Idx);			//Read Filesize in bytes
					Temp32.AsByte[1] = FCD_FAT160_Read_Byte_From_Buffer(29 + Idx);
					Temp32.AsByte[2] = FCD_FAT160_Read_Byte_From_Buffer(30 + Idx);
					Temp32.AsByte[3] = FCD_FAT160_Read_Byte_From_Buffer(31 + Idx);
					FAT_1_mx_file_size[FAT_1_mx_file_idx] = Temp32.AsLong;

					if (FAT_1_mx_cluster == 0)										//Empty File - Assign a free FAT_1_mx_cluster
					{
						idx_fat = 1;
						fat_address = FAT_1_mx_fat_start;							//Move to start of FAT
						FCD_FAT160_MX_Get_Buffer(fat_address);								//Read FAT sector
						while (fat_pointer != 0)								//Scan FAT for free entry
						{
							idx_fat = idx_fat + 1;
							if(idx_fat == FAT_1_FATS_PER_SECT)						//If at the end of the FAT sector
							{
								fat_address = fat_address + 1;
								FCD_FAT160_MX_Get_Buffer(fat_address);						//Read next FAT sector
								idx_fat = 0;
							}

							Temp32.AsByte[0] = FCD_FAT160_Read_Byte_From_Buffer(idx_fat * FAT_1_SECT_ADDR_LEN);			//Extract data FAT_1_mx_cluster address
							Temp32.AsByte[1] = FCD_FAT160_Read_Byte_From_Buffer((idx_fat * FAT_1_SECT_ADDR_LEN) + 1);
							Temp32.AsByte[2] = 0;
							Temp32.AsByte[3] = 0;

							#if (FAT_1_FAT_TYPE == 1 || FAT_1_FAT_TYPE == 2)
								if(FAT_1_mx_fat_system == 1)
								{
									Temp32.AsByte[2] = FCD_FAT160_Read_Byte_From_Buffer((idx_fat * FAT_1_SECT_ADDR_LEN) + 2);
									Temp32.AsByte[3] = FCD_FAT160_Read_Byte_From_Buffer((idx_fat * FAT_1_SECT_ADDR_LEN) + 3);

								}
							#endif

							fat_pointer = Temp32.AsLong;
						}

						FCD_FAT160_Write_Byte_To_Buffer((idx_fat * FAT_1_SECT_ADDR_LEN), 0xFF);							//Write end of file marker into new FAT address
						FCD_FAT160_Write_Byte_To_Buffer(((idx_fat * FAT_1_SECT_ADDR_LEN) + 1), 0xFF);
						#if (FAT_1_FAT_TYPE == 1 || FAT_1_FAT_TYPE == 2)
							if(FAT_1_mx_fat_system == 1)
							{
								FCD_FAT160_Write_Byte_To_Buffer(((idx_fat * FAT_1_SECT_ADDR_LEN) + 2), 0xFF);
								FCD_FAT160_Write_Byte_To_Buffer(((idx_fat * FAT_1_SECT_ADDR_LEN) + 3), 0x0F);
							}
						#endif
						FCD_FAT160_MX_Send_Buffer(fat_address);
						FCD_FAT160_MX_Send_Buffer(fat_address + FAT_1_mx_fat_size);										//Mirror data onto FAT 2

						FCD_FAT160_MX_Get_Buffer(FAT_1_mx_file_pointer[FAT_1_mx_file_idx]);												//Read sector of root directory containing file
						fat_address = ((fat_address - FAT_1_mx_fat_start) * FAT_1_FATS_PER_SECT) + idx_fat;
						FAT_1_mx_cluster = fat_address;

						Temp32.AsLong = FAT_1_mx_cluster;

						FCD_FAT160_Write_Byte_To_Buffer(26 + Idx, Temp32.AsByte[0]);									//Write new FAT_1_mx_cluster value
						FCD_FAT160_Write_Byte_To_Buffer(27 + Idx, Temp32.AsByte[1]);
						#if (FAT_1_FAT_TYPE == 1 || FAT_1_FAT_TYPE == 2)
							if(FAT_1_mx_fat_system == 1)
							{
								FCD_FAT160_Write_Byte_To_Buffer(20 + Idx, Temp32.AsByte[2]);
								FCD_FAT160_Write_Byte_To_Buffer(21 + Idx, Temp32.AsByte[3]);
							}
						#endif
						FCD_FAT160_MX_Send_Buffer(FAT_1_mx_file_pointer[FAT_1_mx_file_idx]);												//Write FAT_1_mx_cluster location to card
					}

					FAT_1_mx_file_pointer[FAT_1_mx_file_idx] = FAT_1_mx_data_start + ((FAT_1_mx_cluster - 2) * FAT_1_mx_sects_per_clust);		//Move to sector containing start of file   - BR 06/10 was *32
					FCD_FAT160_MX_Get_Buffer(FAT_1_mx_file_pointer[FAT_1_mx_file_idx]);													//Read sector
					return MX_ACK_OK;
				}
			}
			FAT_1_mx_file_pointer[FAT_1_mx_file_idx] = FAT_1_mx_file_pointer[FAT_1_mx_file_idx] + 1;												//Move to next sector of folder
		}
		return MX_ERR_FILENOTFOUND;																			//File not found

}

static MX_UINT8 FCD_FAT160_Read_File_Sector()
{
	
		return FCD_FAT160_MX_Get_Buffer(FAT_1_mx_file_pointer[FAT_1_mx_file_idx]);		//Read sector

}

static MX_SINT16 FCD_FAT160_Read_File_Length()
{
	
		long temp;
		temp = FAT_1_mx_file_sector[FAT_1_mx_file_idx] << 9;
		if (temp <= FAT_1_mx_file_size[FAT_1_mx_file_idx])					//If file size greater then sector limit
			return 512;								//Return Sector Full

		temp = FAT_1_mx_file_size[FAT_1_mx_file_idx] % 512;
		return (temp);								//Return index of next available byte

}

static MX_UINT8 FCD_FAT160_Move_To_Next_File_Sector(MX_UINT8 Force_Next_Sector)
{
	
		MX_UINT8 retval;
		retval = FCD_FAT160_Read_Next_File_Sector();				//Try to move to the next sector
		if (Force_Next_Sector)							//If forcing next sector
		{
			if(retval != 0x01)
				return retval;							//Next sector exists and has been read (0) or error with sector chain

			FCD_FAT160_MX_Add_Sector_To_File();					//If last sector in FAT chain then create new link
			//FAT_1_mx_file_sector[FAT_1_mx_file_idx] = FAT_1_mx_file_sector[FAT_1_mx_file_idx] + 1;		//Increment file sector
			return MX_ACK_OK;
		}
		return retval;

}

static MX_UINT8 FCD_FAT160_Append_String_To_File(MX_STRING String, MX_UINT8 MSZ_String)
{
	
		MX_UINT8 idx;
		MX_SINT16 length;
		MX_UINT8 retval;
		MX_UINT8 offset = 0;
		MX_UINT16 Idx16;

		MX_Union32 Temp32;

		for (idx=0;idx<MSZ_String;idx++)
		{
			if(String[idx] == 0)
				MSZ_String = idx;
		}

		length = FCD_FAT160_Read_File_Length();				//Get next empty MX_UINT8acter position
		while (length == 512)						//While MX_UINT8acters in sector full
		{
			retval = FCD_FAT160_Read_Next_File_Sector();		//Load next sector
			if (retval == 0x01)						//If end of file then next sector will be empty
				length = -1;
			else
				length = FCD_FAT160_Read_File_Length();		//Else end of data located in this sector
		}

		if (length == -1)
			length = 512;

		for (idx = 0; idx < MSZ_String; idx++)		//Loop through each MX_UINT8acter in string
		{
			if((length + idx) == 512)				//if string extends onto another sector
			{
				length = 0;
				offset = idx;

				FCD_FAT160_MX_Send_Buffer(FAT_1_mx_file_pointer[FAT_1_mx_file_idx]);			//Write string data in current sector to card
				retval = FCD_FAT160_Read_Next_File_Sector();		//Load next sector

				if (retval == 0x01)
				{
					FCD_FAT160_MX_Add_Sector_To_File();			//If last sector in FAT chain then create new link
				}

				if (retval > 0x01)
					return retval;										//Error occurred - return error
			}

			FCD_FAT160_Write_Byte_To_Buffer((length + (idx - offset)), String[idx]);		//Write MX_UINT8acter from string into buffer
		}

		FCD_FAT160_MX_Send_Buffer(FAT_1_mx_file_pointer[FAT_1_mx_file_idx]);										//Write string data in current sector to card
		FAT_1_mx_file_size[FAT_1_mx_file_idx] = FAT_1_mx_file_size[FAT_1_mx_file_idx] + MSZ_String;								//Update file length
		FCD_FAT160_MX_Get_Buffer(FAT_1_mx_file_address[FAT_1_mx_file_idx]);											//Read file address

		Temp32.AsLong = FAT_1_mx_file_size[FAT_1_mx_file_idx];

		Idx16 = 28 + (FAT_1_mx_file_entry[FAT_1_mx_file_idx] << 5);

		FCD_FAT160_Write_Byte_To_Buffer(Idx16++, Temp32.AsByte[0]);				//Update file length in buffer
		FCD_FAT160_Write_Byte_To_Buffer(Idx16++, Temp32.AsByte[1]);
		FCD_FAT160_Write_Byte_To_Buffer(Idx16++, Temp32.AsByte[2]);
		FCD_FAT160_Write_Byte_To_Buffer(Idx16, Temp32.AsByte[3]);

		FCD_FAT160_MX_Send_Buffer(FAT_1_mx_file_address[FAT_1_mx_file_idx]);									//Update file length on card
		FCD_FAT160_MX_Send_Buffer(FAT_1_mx_file_address[FAT_1_mx_file_idx] + FAT_1_mx_fat_size);						//Mirror data onto FAT 2
		FCD_FAT160_MX_Get_Buffer(FAT_1_mx_file_pointer[FAT_1_mx_file_idx]);									//Read current sector
		return MX_ACK_OK;														//String appended to file

}

static MX_UINT8 FCD_FAT160_Write_File_Sector()
{
	
		short Idx;

		MX_Union32 Temp32;

		if ((FAT_1_mx_file_size[FAT_1_mx_file_idx] >> 9) == (FAT_1_mx_file_sector[FAT_1_mx_file_idx] - 1))	//Is this the last sector of the file
			FAT_1_mx_file_size[FAT_1_mx_file_idx] = (FAT_1_mx_file_size[FAT_1_mx_file_idx] + (512 - FCD_FAT160_Read_File_Length()));

		FCD_FAT160_MX_Send_Buffer(FAT_1_mx_file_pointer[FAT_1_mx_file_idx]);								//Write string data in current sector to card
		FCD_FAT160_MX_Get_Buffer(FAT_1_mx_file_address[FAT_1_mx_file_idx]);									//Read file address

		Temp32.AsLong = FAT_1_mx_file_size[FAT_1_mx_file_idx];

		Idx = 28 + (FAT_1_mx_file_entry[FAT_1_mx_file_idx] << 5);
		FCD_FAT160_Write_Byte_To_Buffer(Idx++, Temp32.AsByte[0]);					//Update file length in buffer
		FCD_FAT160_Write_Byte_To_Buffer(Idx++, Temp32.AsByte[1]);
		FCD_FAT160_Write_Byte_To_Buffer(Idx++, Temp32.AsByte[2]);
		FCD_FAT160_Write_Byte_To_Buffer(Idx, Temp32.AsByte[3]);

		FCD_FAT160_MX_Send_Buffer(FAT_1_mx_file_address[FAT_1_mx_file_idx]);								//Update file length on card
		FCD_FAT160_MX_Send_Buffer(FAT_1_mx_file_address[FAT_1_mx_file_idx] + FAT_1_mx_fat_size);					//Mirror data onto FAT 2
		FCD_FAT160_MX_Get_Buffer(FAT_1_mx_file_pointer[FAT_1_mx_file_idx]);								//Read current sector

		return MX_ACK_OK;

}

static MX_UINT8 FCD_FAT160_Create_File(MX_STRING File_Name, MX_UINT8 MSZ_File_Name)
{
	
		MX_UINT8 i, j;
		MX_UINT16 Idx;

		MX_Union16 Temp16;

		if ( FCD_FAT160_Open_File(File_Name, MSZ_File_Name) != MX_ERR_FILENOTFOUND )
			return 0x01;													//File Already exists

		//MX_Format_File_String(File_Name, MSZ_File_Name);					//Convert filename to 8.3 format - Not needed as open_file calls this
		FAT_1_mx_file_pointer[FAT_1_mx_file_idx] = FAT_1_mx_folder_start[FAT_1_mx_file_idx];								//Move to start of root
		while (FAT_1_mx_file_pointer[FAT_1_mx_file_idx] < (FAT_1_mx_folder_start[FAT_1_mx_file_idx] + FAT_1_mx_folder_size[FAT_1_mx_file_idx]))
		{
			FCD_FAT160_MX_Get_Buffer(FAT_1_mx_file_pointer[FAT_1_mx_file_idx]);								//Read sector of root directory
			for(i=0;i<16;i++)												//16 file or directory references per sector
			{
				Idx = i << 5;
				j = FCD_FAT160_Read_Byte_From_Buffer(Idx);
				if (( j == 0xe5) || ( j == 0x00))							//Deleted or unused entry
				{
					for (j=0;j<11;j++)
					{
						FCD_FAT160_Write_Byte_To_Buffer(Idx++, FAT_1_mx_name_ext[j]);
					}

					FCD_FAT160_Write_Byte_To_Buffer(Idx++, 0x20);						//File Attribute
					FCD_FAT160_Write_Byte_To_Buffer(Idx++, 0x18);						//Reserved for NT
					FCD_FAT160_Write_Byte_To_Buffer(Idx++, 0);							//Creation time
					Temp16.AsInt = FAT_1_FILE_CREATETIME;
					FCD_FAT160_Write_Byte_To_Buffer(Idx++, Temp16.AsByte[0]);
					FCD_FAT160_Write_Byte_To_Buffer(Idx++, Temp16.AsByte[1]);
					Temp16.AsInt = FAT_1_FILE_CREATEDATE;
					FCD_FAT160_Write_Byte_To_Buffer(Idx++, Temp16.AsByte[0]);		//Creation date
					FCD_FAT160_Write_Byte_To_Buffer(Idx++, Temp16.AsByte[1]);
					FCD_FAT160_Write_Byte_To_Buffer(Idx++, Temp16.AsByte[0]);		//Access date
					FCD_FAT160_Write_Byte_To_Buffer(Idx++, Temp16.AsByte[1]);
					FCD_FAT160_Write_Byte_To_Buffer(Idx++, 0x00);
					FCD_FAT160_Write_Byte_To_Buffer(Idx++, 0x00);
					Temp16.AsInt = FAT_1_FILE_CREATETIME;
					FCD_FAT160_Write_Byte_To_Buffer(Idx++, Temp16.AsByte[0]);		//Modified time 0 no modification entry
					FCD_FAT160_Write_Byte_To_Buffer(Idx++, Temp16.AsByte[1]);
					Temp16.AsInt = FAT_1_FILE_CREATEDATE;
					FCD_FAT160_Write_Byte_To_Buffer(Idx++, Temp16.AsByte[0]);		//Modified date
					FCD_FAT160_Write_Byte_To_Buffer(Idx++, Temp16.AsByte[1]);

					for (j=26;j<32;j++)												//Sector location and length
					{
						FCD_FAT160_Write_Byte_To_Buffer(Idx++, 0);
					}
					FCD_FAT160_MX_Send_Buffer(FAT_1_mx_file_pointer[FAT_1_mx_file_idx]);
					return MX_ACK_OK;												//File created
				}
			}
			FAT_1_mx_file_pointer[FAT_1_mx_file_idx] = FAT_1_mx_file_pointer[FAT_1_mx_file_idx] + 1;
		}
		return MX_ERR_ROOTFULL;														//No space left in root directory

}

static MX_UINT8 FCD_FAT160_Delete_File(MX_STRING File_Name, MX_UINT8 MSZ_File_Name)
{
	
		MX_UINT8 name_comp[11];
		MX_UINT32 fat_address;
		MX_UINT8 i;
		MX_UINT16 Idx;

		MX_Union16 Temp16;

		#if (FAT_1_FAT_TYPE == 0)
			MX_UINT16 temp_mx_cluster;
		#endif
		#if (FAT_1_FAT_TYPE == 1 || FAT_1_FAT_TYPE == 2)
			MX_UINT32 temp_mx_cluster;
		#endif

		FCD_FAT160_MX_Format_File_String(File_Name, MSZ_File_Name);							//Convert filename to 8.3 format
		FAT_1_mx_file_pointer[FAT_1_mx_file_idx] = FAT_1_mx_folder_start[FAT_1_mx_file_idx];									//Move to start of root

		while (FAT_1_mx_file_pointer[FAT_1_mx_file_idx] <= (FAT_1_mx_folder_start[FAT_1_mx_file_idx] + FAT_1_mx_folder_size[FAT_1_mx_file_idx]))
		{
			FCD_FAT160_MX_Get_Buffer(FAT_1_mx_file_pointer[FAT_1_mx_file_idx]);								//Read sector of root directory
			for(i=0;i<16;i++)													//16 file or directory references per sector
			{
				Idx = i << 5;

				name_comp[0] = FCD_FAT160_Read_Byte_From_Buffer(Idx);						//Move DOS 8.3 Filename into 2nd comparison buffer
				name_comp[1] = FCD_FAT160_Read_Byte_From_Buffer(1 + Idx);
				name_comp[2] = FCD_FAT160_Read_Byte_From_Buffer(2 + Idx);
				name_comp[3] = FCD_FAT160_Read_Byte_From_Buffer(3 + Idx);
				name_comp[4] = FCD_FAT160_Read_Byte_From_Buffer(4 + Idx);
				name_comp[5] = FCD_FAT160_Read_Byte_From_Buffer(5 + Idx);
				name_comp[6] = FCD_FAT160_Read_Byte_From_Buffer(6 + Idx);
				name_comp[7] = FCD_FAT160_Read_Byte_From_Buffer(7 + Idx);
				name_comp[8] = FCD_FAT160_Read_Byte_From_Buffer(8 + Idx);
				name_comp[9] = FCD_FAT160_Read_Byte_From_Buffer(9 + Idx);
				name_comp[10] = FCD_FAT160_Read_Byte_From_Buffer(10 + Idx);

				if (FCI_COMPARE(FAT_1_mx_name_ext,11,name_comp,11,1) == 0)			//Perform filename comparison
				{
					Temp16.AsByte[0] = FCD_FAT160_Read_Byte_From_Buffer(26 + Idx);			//Read Cluster of data start
					Temp16.AsByte[1] = FCD_FAT160_Read_Byte_From_Buffer(27 + Idx);
					FAT_1_mx_cluster = Temp16.AsInt;

					FCD_FAT160_Write_Byte_To_Buffer(26 + Idx, 0);							//Overwrite FAT_1_mx_cluster value
					FCD_FAT160_Write_Byte_To_Buffer(27 + Idx, 0);
					#if(FAT_1_FAT_TYPE == 1 || FAT_1_FAT_TYPE == 2)
						if (FAT_1_mx_fat_system == 1)
						{
							FCD_FAT160_Write_Byte_To_Buffer(20 + Idx, 0);
							FCD_FAT160_Write_Byte_To_Buffer(21 + Idx, 0);
						}
					#endif

					FCD_FAT160_Write_Byte_To_Buffer(28 + Idx, 0);							//Clear file size
					FCD_FAT160_Write_Byte_To_Buffer(29 + Idx, 0);
					FCD_FAT160_Write_Byte_To_Buffer(30 + Idx, 0);
					FCD_FAT160_Write_Byte_To_Buffer(31 + Idx, 0);
					FCD_FAT160_Write_Byte_To_Buffer(Idx, 0xe5);							//Set first byte to free file flag
					FCD_FAT160_MX_Send_Buffer(FAT_1_mx_file_pointer[FAT_1_mx_file_idx]);						//Write the free file flag to the card

					while (FAT_1_mx_cluster >= 0x02 && FAT_1_mx_cluster <= (FAT_1_MX_EOF_MARKER + 1))			//While end of file not reached
					{
						if (FAT_1_mx_cluster > FAT_1_MX_EOF_MARKER)
							return 0xFE;										//Problem with FAT entry

						fat_address = FAT_1_mx_fat_start;							//Move to start of FAT
						while(FAT_1_mx_cluster >= FAT_1_FATS_PER_SECT)
						{
							fat_address = fat_address + 1;						//Move to next sector of FAT
							FAT_1_mx_cluster = FAT_1_mx_cluster - FAT_1_FATS_PER_SECT;
						}
						FCD_FAT160_MX_Get_Buffer(fat_address);								//Read FAT sector

						temp_mx_cluster = FAT_1_mx_cluster;
						Temp16.AsByte[0] = FCD_FAT160_Read_Byte_From_Buffer(temp_mx_cluster * FAT_1_FATS_PER_SECT);			//Read next FAT_1_mx_cluster value
						Temp16.AsByte[1] = FCD_FAT160_Read_Byte_From_Buffer((temp_mx_cluster * FAT_1_FATS_PER_SECT) + 1);
						FAT_1_mx_cluster = Temp16.AsInt;

						FCD_FAT160_Write_Byte_To_Buffer((temp_mx_cluster * FAT_1_FATS_PER_SECT), 0x00);				//Overwrite FAT entry
						FCD_FAT160_Write_Byte_To_Buffer(((temp_mx_cluster * FAT_1_FATS_PER_SECT) + 1), 0x00);

						FCD_FAT160_MX_Send_Buffer(fat_address);
						FCD_FAT160_MX_Send_Buffer(fat_address + FAT_1_mx_fat_size);				//Mirror data onto FAT 2
					}
					return 0;													//File deleted correctly
				}
			}
			FAT_1_mx_file_pointer[FAT_1_mx_file_idx] = FAT_1_mx_file_pointer[FAT_1_mx_file_idx] + 1;
		}
		return MX_ERR_FILENOTFOUND;												//File not found

}

static void FCD_FAT160_Write_Byte_To_Buffer(MX_SINT16 Address, MX_UINT8 Data)
{
	
		if (Address > 255)				//BufferH
		{
			Address = Address - 256;
			FAT_1_mx_card_bufferh[Address] = Data;
		}
		else							//BufferL
		{
			FAT_1_mx_card_bufferl[Address] = Data;
		}

}

static MX_UINT8 FCD_FAT160_Read_Byte_From_Buffer(MX_SINT16 Address)
{
	
		if (Address > 255)						//BufferH
		{
			Address = Address - 256;
			return (FAT_1_mx_card_bufferh[Address]);
		}
		else return (FAT_1_mx_card_bufferl[Address]);	//BufferL

}

static MX_UINT8 FCD_FAT160_Open_Folder(MX_STRING Folder_Name, MX_UINT8 MSZ_Folder_Name)
{
	
	// ".." - Up a level
	// "root" - Root directory
	// "foldername" - Down a level

		MX_UINT8 i;
		MX_UINT8 name_comp[11];
		MX_UINT16 Idx;

		MX_Union32 Temp32;

		//Root Directory
		if (Folder_Name[0] == 'r' && Folder_Name[1] == 'o' && Folder_Name[2] == 'o' && Folder_Name[3] == 't')
		{
			FAT_1_mx_folder_start[FAT_1_mx_file_idx] = FAT_1_mx_root_start;		//Assign root start address to folder start
			FAT_1_mx_folder_size[FAT_1_mx_file_idx] = FAT_1_mx_root_sectors;		//Assign root size to folder size
			return (0);								//Root Directory Specified
		}

		//Up a level
		if (Folder_Name[0] == '.' && Folder_Name[1] == '.')
		{
			FAT_1_mx_name_ext[0] = 0x2E;			// Assign search string with ".."
			FAT_1_mx_name_ext[1] = 0x2E;
			FAT_1_mx_name_ext[2] = 0x20;
			FAT_1_mx_name_ext[3] = 0x20;
			FAT_1_mx_name_ext[4] = 0x20;
			FAT_1_mx_name_ext[5] = 0x20;
			FAT_1_mx_name_ext[6] = 0x20;
			FAT_1_mx_name_ext[7] = 0x20;
			FAT_1_mx_name_ext[8] = 0x20;
			FAT_1_mx_name_ext[9] = 0x20;
			FAT_1_mx_name_ext[10] = 0x20;
		}

		else
			FCD_FAT160_MX_Format_File_String(Folder_Name, MSZ_Folder_Name);					//Format folder string to match 8 MX_UINT8acter folder name

		FAT_1_mx_file_pointer[FAT_1_mx_file_idx] = FAT_1_mx_folder_start[FAT_1_mx_file_idx];										//Move to start of folder

		while (FAT_1_mx_file_pointer[FAT_1_mx_file_idx] < (FAT_1_mx_folder_start[FAT_1_mx_file_idx] + FAT_1_mx_folder_size[FAT_1_mx_file_idx]))
		{
			FCD_FAT160_MX_Get_Buffer(FAT_1_mx_file_pointer[FAT_1_mx_file_idx]);										//Read sector of root directory
			for(i=0;i<16;i++)														//16 file or directory references per sector
			{
				Idx = i << 5;

				name_comp[0] = FCD_FAT160_Read_Byte_From_Buffer(Idx);					//Move DOS 8.3 Filename into 2nd comparison buffer
				name_comp[1] = FCD_FAT160_Read_Byte_From_Buffer(1 + Idx);
				name_comp[2] = FCD_FAT160_Read_Byte_From_Buffer(2 + Idx);
				name_comp[3] = FCD_FAT160_Read_Byte_From_Buffer(3 + Idx);
				name_comp[4] = FCD_FAT160_Read_Byte_From_Buffer(4 + Idx);
				name_comp[5] = FCD_FAT160_Read_Byte_From_Buffer(5 + Idx);
				name_comp[6] = FCD_FAT160_Read_Byte_From_Buffer(6 + Idx);
				name_comp[7] = FCD_FAT160_Read_Byte_From_Buffer(7 + Idx);
				name_comp[8] = FCD_FAT160_Read_Byte_From_Buffer(8 + Idx);
				name_comp[9] = FCD_FAT160_Read_Byte_From_Buffer(9 + Idx);
				name_comp[10] = FCD_FAT160_Read_Byte_From_Buffer(10 + Idx);

				if (FCI_COMPARE(FAT_1_mx_name_ext,11,name_comp,11,1) == 0)				//Perform filename comparison
				{
					Temp32.AsByte[0] = FCD_FAT160_Read_Byte_From_Buffer(26 + Idx);							//Read Cluster of folder start
					Temp32.AsByte[1] = FCD_FAT160_Read_Byte_From_Buffer(27 + Idx);
					Temp32.AsByte[2] = 0;
					Temp32.AsByte[3] = 0;

					#if	(FAT_1_FAT_TYPE == 1 || FAT_1_FAT_TYPE == 2)
						if (FAT_1_mx_fat_system == 1)
						{
							Temp32.AsByte[2] = FCD_FAT160_Read_Byte_From_Buffer(20 + Idx);
							Temp32.AsByte[3] = FCD_FAT160_Read_Byte_From_Buffer(21 + Idx);
						}
					#endif

					FAT_1_mx_cluster = Temp32.AsLong;

					if (FAT_1_mx_cluster > 1)
					{
						FAT_1_mx_folder_start[FAT_1_mx_file_idx] = FAT_1_mx_data_start + ((FAT_1_mx_cluster - 2) * FAT_1_mx_sects_per_clust);		//Assign folder start address - BR 06/10 was * 32
						FAT_1_mx_folder_size[FAT_1_mx_file_idx] = FAT_1_mx_sects_per_clust;											//Assign folder size - BR 06/10 was *32											//Assign folder size
					}
					else
					{
						FAT_1_mx_folder_start[FAT_1_mx_file_idx] = FAT_1_mx_root_start;							//Assign root start address to folder start
						FAT_1_mx_folder_size[FAT_1_mx_file_idx] = FAT_1_mx_root_sectors;							//Assign root size to folder size
					}
					return MX_ACK_OK;												//Folder found and moved
				}
			}
			FAT_1_mx_file_pointer[FAT_1_mx_file_idx] = FAT_1_mx_file_pointer[FAT_1_mx_file_idx] + 1;						//Move to next sector of folder
		}
		return MX_ERR_FILENOTFOUND;													//Folder not found

}

static MX_SINT16 FCD_FAT160_Scan_Current_Folder(MX_SINT16 Current_Idx, MX_UINT8 Scan_Type)
{
	
		MX_UINT8 i;
		MX_UINT16 Idx;

		if (Current_Idx < (FAT_1_mx_folder_size[FAT_1_mx_file_idx] * 16))
		{
			FAT_1_mx_file_pointer[FAT_1_mx_file_idx] = FAT_1_mx_folder_start[FAT_1_mx_file_idx];							//Move to start of folder
			while(Current_Idx >= 16)										//While address is not in the current sector
			{
				Current_Idx = Current_Idx - 16;								//Modify address value
				FAT_1_mx_file_pointer[FAT_1_mx_file_idx] = FAT_1_mx_file_pointer[FAT_1_mx_file_idx] + 1;				//Increment sector address
			}

			FCD_FAT160_MX_Get_Buffer(FAT_1_mx_file_pointer[FAT_1_mx_file_idx]);								//Read sector of root directory

			Idx = Current_Idx * 32;

			i = FCD_FAT160_Read_Byte_From_Buffer(Idx);
			if ((i == 0xe5) || (i == 0x00))  								//Deleted or unused entry
				return MX_ACK_FILEEMPTY;									//Address is empty

			if ( FCD_FAT160_Read_Byte_From_Buffer((Idx) + 2) == 0x00)
				return MX_ACK_FILEEMPTY;									//Address is empty

			if(Scan_Type)	//scan for folder
			{
				if (( FCD_FAT160_Read_Byte_From_Buffer(Idx + 11) & 0x10) == 0)			//If a file has been found
					return MX_ACK_FILETYPE;									//Address in use but incorrect data type
			}
			else			//scan for file
			{
				if (( FCD_FAT160_Read_Byte_From_Buffer(Idx + 11) & 0x20) == 0)			//If a folder has been found
					return MX_ACK_FILETYPE;									//Address in use but incorrect data type
			}

			for (i=0;i<11;i++)
				FAT_1_mx_name_ext[i] = FCD_FAT160_Read_Byte_From_Buffer(Idx + i);			//Read string from address

			if(Scan_Type == 0)												//If scanning for a file then rearrange 8.3 filename back into string
			{
				for (i=0;i<7;i++)
				{
					if (FAT_1_mx_name_ext[i] == 0x20)								//If a padding space has been found
						break;
				}
				FAT_1_mx_name_ext[i] = '.';										//Add the '.' seperator to the filename
				FAT_1_mx_name_ext[i + 1] = FCD_FAT160_Read_Byte_From_Buffer(Idx + 8);
				FAT_1_mx_name_ext[i + 2] = FCD_FAT160_Read_Byte_From_Buffer(Idx + 9);
				FAT_1_mx_name_ext[i + 3] = FCD_FAT160_Read_Byte_From_Buffer(Idx + 10);
				for (i=i+4;i<12;i++)
					FAT_1_mx_name_ext[i] = ' ';
			}
			return MX_ACK_OK;												//File/folder found and stored into string array
		}
		return MX_ACK_EOF;													//End of folder reached

}

static MX_UINT8 FCD_FAT160_Read_Byte_From_Scan(MX_UINT8 idx)
{
	
		if(idx > 11)
			return 0;				//String buffer 12 MX_UINT8s long max
		return (FAT_1_mx_name_ext[idx]);	//Return MX_UINT8acter from string

}

static MX_UINT8 FCD_FAT160_MX_Init_Card()
{
	
		MX_UINT8 RetVal, SD_version;
		MX_SINT16 i;

		FC_CAL_Bit_High_DDR (FAT_1_MX_SPI_FAT_CS_PORT, FAT_1_MX_SPI_FAT_CS_TRIS, FAT_1_MX_SPI_FAT_CS_PIN);	// Chip Select pin is disabled

		//Init SPI
		FAT_1_SPI_Master_Init();							//Call initialise function

		delay_ms(50);														//Wait for card to power up

		for(i = 0; i < 10; i++)												//Start CARD in SPI mode
		{
			FAT_1_SPI_Master_Byte(0xFF);					//Send 10*8=80 clock pulses
		}

		FC_CAL_Bit_Low ( FAT_1_MX_SPI_FAT_CS_PORT, FAT_1_MX_SPI_FAT_CS_PIN);		// Chip Select pin is enabled													//Wait 50us
		i=0;

		do
		{
			RetVal = FCD_FAT160_MX_Send_Cmd(GO_IDLE_STATE, 0x00000000);					//Command 0 - Goto Idle State - Resets card
			i++;
			if (i > 0x20)
				return MX_ERR_NOCARD;

		} while(RetVal != 0x01);

		FC_CAL_Bit_High ( FAT_1_MX_SPI_FAT_CS_PORT, FAT_1_MX_SPI_FAT_CS_PIN);		// Chip Select pin is disabled

		FAT_1_SPI_Master_Byte(0xFF);
		FAT_1_SPI_Master_Byte(0xFF);

		SD_version = 2;
		i=0;

		do
		{
			RetVal = FCD_FAT160_MX_Send_Cmd(SEND_IF_COND,0x000001AA); //Check power supply status, mendatory for SDHC card
			i++;
			if(i>0xfe)
			{
				  SD_version = 1;
				  FAT_1_mx_card_type = 1;
				  break;
			} //time out

		}while(RetVal != 0x01);

		i=0;

		do
		{
			RetVal = FCD_FAT160_MX_Send_Cmd(APP_CMD, 0x00000000); //CMD55, must be sent before sending any ACMD command
			RetVal = FCD_FAT160_MX_Send_Cmd(SD_SEND_OP_COND, 0x40000000); //ACMD41

			i++;
			if(i>0xfe)
		   	{
			  	return MX_ERR_NORESP;  //time out, card initialization failed
			}

		}while(RetVal != 0x00);

		i = 0;
		FAT_1_mx_sdhc_flag = 0;

		if (SD_version == 2)
		{
		   do
		   {
			 RetVal = FCD_FAT160_MX_Send_Cmd(READ_OCR, 0x00000000);
			 i++;
			 if(i>0xfe)
			 {
			   FAT_1_mx_card_type = 0;
			   break;
			 } //time out

		   }while(RetVal != 0x00);

		   if(FAT_1_mx_sdhc_flag == 1) FAT_1_mx_card_type = 2;
		   else FAT_1_mx_card_type = 3;
		}

		//Need a good way of applying this speed update!!!

		//FAT_1_SPI_Master_Uninit();				//Disable Low Speed
		//FAT_1_FAT.AsByteus_mode = 1;				//SPI Bus Mode	//Check this value
		//FAT_1_SPI_Master_Init ();				//Enable Hi Speed

		FAT_1_SPI_Set_Prescaler(0);				//1:4

		return MX_ACK_OK;						//Card Ready

}

static MX_UINT8 FCD_FAT160_MX_Send_Buffer(long address)
{
	
		MX_UINT16 idx;
		MX_UINT8 retval;

		if(FAT_1_mx_sdhc_flag == 0)
			address = address << 9;

		retval = FCD_FAT160_MX_Send_Cmd(WRITE_SINGLE_BLOCK, address);

		if (retval)
		{
			FC_CAL_Bit_High ( FAT_1_MX_SPI_FAT_CS_PORT, FAT_1_MX_SPI_FAT_CS_PIN);			//CARD-Disabled
			FAT_1_SPI_Master_Byte(0xFF);
			return MX_ERR_NOACK;													//Command not acknowledged
		}

		FC_CAL_Bit_Low ( FAT_1_MX_SPI_FAT_CS_PORT, FAT_1_MX_SPI_FAT_CS_PIN);

		FAT_1_SPI_Master_Byte(0xFE);													//Send Start Byte
		for (idx=0; idx < 256; idx++)												//Write Low Buffer
		{
			FAT_1_SPI_Master_Byte(FAT_1_mx_card_bufferl[idx]);
		}
		for (idx=0; idx < 256; idx++)												//Write High Buffer
		{
			FAT_1_SPI_Master_Byte(FAT_1_mx_card_bufferh[idx]);
		}
		FAT_1_SPI_Master_Byte(0xFF);								//Send 2 dummy bytes to skip CRC
		FAT_1_SPI_Master_Byte(0xFF);

		retval = FAT_1_SPI_Master_Byte(0xFF);					//Check if CARD is still busy
		if((retval & 0x1F) != 0x05)
		{
			FC_CAL_Bit_High ( FAT_1_MX_SPI_FAT_CS_PORT, FAT_1_MX_SPI_FAT_CS_PIN);				// Chip Select pin is disabled
			return MX_ERR_TOUT;					//Read timed out
		}

		//Wait for card to complete writing
		idx = 0;
		while (!FAT_1_SPI_Master_Byte(0xFF))
		{
			if(idx++ > 0xfffe)
			{
				FC_CAL_Bit_High ( FAT_1_MX_SPI_FAT_CS_PORT, FAT_1_MX_SPI_FAT_CS_PIN);				// Chip Select pin is disabled
				return MX_ERR_TOUT;				//Read timed out
			}
		}

		FC_CAL_Bit_High ( FAT_1_MX_SPI_FAT_CS_PORT, FAT_1_MX_SPI_FAT_CS_PIN);
		FAT_1_SPI_Master_Byte(0xFF);
		FC_CAL_Bit_Low ( FAT_1_MX_SPI_FAT_CS_PORT, FAT_1_MX_SPI_FAT_CS_PIN);

		//double check that card is no longer busy
		idx = 0;
		while (!FAT_1_SPI_Master_Byte(0xFF))
		{
			if(idx++ > 0xfffe)
			{
				FC_CAL_Bit_High ( FAT_1_MX_SPI_FAT_CS_PORT, FAT_1_MX_SPI_FAT_CS_PIN);				// Chip Select pin is disabled
				return MX_ERR_TOUT;				//Read timed out
			}
		}

		FC_CAL_Bit_High ( FAT_1_MX_SPI_FAT_CS_PORT, FAT_1_MX_SPI_FAT_CS_PIN);

		return MX_ACK_OK;						//Write Complete

}

static MX_UINT8 FCD_FAT160_MX_Get_Buffer(long address)
{
	
		MX_SINT16 idx;
		MX_UINT8 temp;
		MX_UINT16 count;

		if(FAT_1_mx_sdhc_flag == 0)
			address = address << 9;

		FCD_FAT160_MX_Clear_Buffer();

		temp = FCD_FAT160_MX_Send_Cmd(READ_SINGLE_BLOCK, address);

		if (temp != 0)
		{
			FC_CAL_Bit_High ( FAT_1_MX_SPI_FAT_CS_PORT, FAT_1_MX_SPI_FAT_CS_PIN);			//CARD-Disabled
			FAT_1_SPI_Master_Byte(0xFF);
			return MX_ERR_NOACK;													//Read Not Acknowledged
		}

		FC_CAL_Bit_Low ( FAT_1_MX_SPI_FAT_CS_PORT, FAT_1_MX_SPI_FAT_CS_PIN);

		count = 10000;
		do
		{
			temp = FAT_1_SPI_Master_Byte(0xFF);
		}
		while ((temp != 0xFE) && (count--));			//Wait for data ready

		if (count == 0)
		{
			FC_CAL_Bit_High ( FAT_1_MX_SPI_FAT_CS_PORT, FAT_1_MX_SPI_FAT_CS_PIN);
			return MX_ERR_TOUT;														//Read Timed Out
		}

		for (idx=0; idx < 256; idx++)												//Read Low Buffer
		{
			FAT_1_mx_card_bufferl[idx] = FAT_1_SPI_Master_Byte(0xFF);
		}

		for (idx=0; idx < 256; idx++)												//Read High Buffer
		{
			FAT_1_mx_card_bufferh[idx] = FAT_1_SPI_Master_Byte(0xFF);
		}

		FAT_1_SPI_Master_Byte(0xFF);													//Skip 16-Bit CRC
		FAT_1_SPI_Master_Byte(0xFF);

		FAT_1_SPI_Master_Byte(0xFF);													//Trailing byte

		FC_CAL_Bit_High ( FAT_1_MX_SPI_FAT_CS_PORT, FAT_1_MX_SPI_FAT_CS_PIN);				// Chip Select pin is disabled
		return MX_ACK_OK;															//Read Complete

}

static void FCD_FAT160_MX_Format_File_String(MX_STRING File_Name, MX_UINT8 MSZ_File_Name)
{
	
		MX_UINT8 	i, j;
		MX_UINT8	filename[12];

		for (i=0;i<11;i++)
		{
			FAT_1_mx_name_ext[i] = 0x20;									//Fill name variable with spaces
		}

		FCI_TOUPPER(File_Name, MSZ_File_Name, (char *) filename, 12);			//convert to uppercase

		for (i=0; i<8; i++)	//Copy file name to comparison variable
		{
			if (filename[i] == '.')
				break;
			if (filename[i] == 0)
				break;

			FAT_1_mx_name_ext[i] = filename[i];
		}

		if(filename[i] == '.')											//Find the '.' seperator
		{
			i++;
			j = i;														//and then shift the extension
			for(i=8;i<11; i++)
			{
				if (filename[j] == 0)
					break;

				FAT_1_mx_name_ext[i] = filename[j];
				j++;
			}
		}

		/*
		//Debug Information
		FCD_LCDDisplay0_Clear();
		FCD_LCDDisplay0_PrintString(filename, 12);
		FCD_LCDDisplay0_Cursor(0,1);
		FCD_LCDDisplay0_PrintString(FAT_1_mx_name_ext, 12);
		delay_s(2); */


}

static void FCD_FAT160_MX_Add_Sector_To_File()
{
	
		MX_UINT32 idx_fat;
		MX_UINT32 fat_address;

		#if (FAT_1_FAT_TYPE == 0)
			MX_UINT16 fat_pointer = 0xFFFF;				//16-bit FAT pointer
		#endif
		#if (FAT_1_FAT_TYPE == 1)
			MX_UINT32 fat_pointer = 0x0FFFFFFF;			//32-bit FAT pointer
		#endif
		#if (FAT_1_FAT_TYPE == 2)
			MX_UINT32 fat_pointer;
			if (FAT_1_mx_fat_system == 1)
				fat_pointer = 0x0FFFFFFF;					//32-bit FAT pointer
			else
				fat_pointer = 0xFFFF;						//16-bit FAT pointer
		#endif

		MX_Union32 Temp32;

		idx_fat = 1;
		fat_address = FAT_1_mx_fat_start;							//Move to start of FAT
		FCD_FAT160_MX_Get_Buffer(fat_address);							//Read FAT sector
		while (fat_pointer > 0)								//Scan FAT for free entry
		{
			idx_fat = (MX_UINT32) idx_fat + 1;					//Increment FAT address - Start at address 2
			if(idx_fat == FAT_1_FATS_PER_SECT)					//If at the end of the FAT sector
			{
				fat_address = fat_address + 1;
				FCD_FAT160_MX_Get_Buffer(fat_address);					//Read next FAT sector
				idx_fat = 0;
			}

			Temp32.AsByte[0] = FCD_FAT160_Read_Byte_From_Buffer(idx_fat * FAT_1_SECT_ADDR_LEN);			//Extract data FAT_1_mx_cluster address
			Temp32.AsByte[1] = FCD_FAT160_Read_Byte_From_Buffer((idx_fat * FAT_1_SECT_ADDR_LEN) + 1);
			Temp32.AsByte[2] = 0;
			Temp32.AsByte[3] = 0;

			#if (FAT_1_FAT_TYPE == 1 || FAT_1_FAT_TYPE == 2)
				if (FAT_1_mx_fat_system == 1)
				{
					Temp32.AsByte[2] = FCD_FAT160_Read_Byte_From_Buffer((idx_fat * FAT_1_SECT_ADDR_LEN) + 2);
					Temp32.AsByte[3] = FCD_FAT160_Read_Byte_From_Buffer((idx_fat * FAT_1_SECT_ADDR_LEN) + 3);
				}
			#endif

			fat_pointer = Temp32.AsLong;
		}

		FCD_FAT160_Write_Byte_To_Buffer((idx_fat * FAT_1_SECT_ADDR_LEN), 0xFF);					//Write end of file marker into new FAT address
		FCD_FAT160_Write_Byte_To_Buffer(((idx_fat * FAT_1_SECT_ADDR_LEN) + 1), 0xFF);

		#if (FAT_1_FAT_TYPE == 1 || FAT_1_FAT_TYPE == 2)
			if (FAT_1_mx_fat_system == 1)
			{
				FCD_FAT160_Write_Byte_To_Buffer(((idx_fat * FAT_1_SECT_ADDR_LEN) + 2), 0xFF);
				FCD_FAT160_Write_Byte_To_Buffer(((idx_fat * FAT_1_SECT_ADDR_LEN) + 3), 0x0F);
			}
		#endif

		FCD_FAT160_MX_Send_Buffer(fat_address);
		FCD_FAT160_MX_Send_Buffer(fat_address + FAT_1_mx_fat_size);				//Mirror data onto FAT 2

		fat_address = ((fat_address - FAT_1_mx_fat_start) * FAT_1_FATS_PER_SECT) + idx_fat;
		idx_fat = FAT_1_mx_cluster;
		FAT_1_mx_cluster = fat_address;								//Store new FAT_1_mx_cluster address

		fat_address = FAT_1_mx_fat_start;
		while (idx_fat >= FAT_1_FATS_PER_SECT)
		{
			idx_fat = idx_fat - FAT_1_FATS_PER_SECT;
			fat_address = fat_address + 1;
		}
		FCD_FAT160_MX_Get_Buffer(fat_address);

		Temp32.AsLong = FAT_1_mx_cluster;

		FCD_FAT160_Write_Byte_To_Buffer((idx_fat * FAT_1_SECT_ADDR_LEN), Temp32.AsByte[0]);				//Update old FAT address
		FCD_FAT160_Write_Byte_To_Buffer(((idx_fat * FAT_1_SECT_ADDR_LEN) + 1), Temp32.AsByte[1]);

		#if (FAT_1_FAT_TYPE == 1 || FAT_1_FAT_TYPE == 2)
			if (FAT_1_mx_fat_system == 1)
			{
				FCD_FAT160_Write_Byte_To_Buffer(((idx_fat * FAT_1_SECT_ADDR_LEN) + 2), Temp32.AsByte[2]);
				FCD_FAT160_Write_Byte_To_Buffer(((idx_fat * FAT_1_SECT_ADDR_LEN) + 3), Temp32.AsByte[3]);
			}
		#endif

		FCD_FAT160_MX_Send_Buffer(fat_address);
		FCD_FAT160_MX_Send_Buffer(fat_address + FAT_1_mx_fat_size);				//Mirror data onto FAT 2

		FAT_1_mx_file_sector[FAT_1_mx_file_idx] = FAT_1_mx_file_sector[FAT_1_mx_file_idx] + 1;						//Increment file sector
		FAT_1_mx_file_pointer[FAT_1_mx_file_idx] = (MX_UINT32) FAT_1_mx_data_start + ((FAT_1_mx_cluster - 2) * FAT_1_mx_sects_per_clust);//Move to next sector in file		BR 06/10 was * 32
		FCD_FAT160_MX_Get_Buffer(FAT_1_mx_file_pointer[FAT_1_mx_file_idx]);

}

static void FCD_FAT160_MX_Clear_Buffer()
{
	
		MX_SINT16 count;

		for (count = 0; count < 256; count++)
		{
			FAT_1_mx_card_bufferh[count] = 0x00;
			FAT_1_mx_card_bufferl[count] = 0x00;
		}

}

static MX_UINT8 FCD_FAT160_Read_Next_File_Sector()
{
	
		#if (FAT_1_FAT_TYPE == 0)
			MX_UINT16 temp_mx_cluster;
			MX_UINT16 old_mx_cluster;
		#endif
		#if (FAT_1_FAT_TYPE == 1 || FAT_1_FAT_TYPE == 2)
			MX_UINT32 temp_mx_cluster;
			MX_UINT32 old_mx_cluster;
		#endif

		MX_UINT32 fat_address;
		MX_UINT8 retval;

		MX_Union32 Temp32;

		FAT_1_mx_file_pointer[FAT_1_mx_file_idx] = FAT_1_mx_file_pointer[FAT_1_mx_file_idx] + 1;								//Increment address
		if (((FAT_1_mx_file_pointer[FAT_1_mx_file_idx] - FAT_1_mx_data_start) % FAT_1_mx_sects_per_clust) == 0)		//If end of FAT_1_mx_cluster reached then find next FAT_1_mx_cluster BR 06/10 was % 32
		{
			temp_mx_cluster = FAT_1_mx_cluster;
			fat_address = FAT_1_mx_fat_start;												//Move to start of FAT
			while (temp_mx_cluster >= FAT_1_FATS_PER_SECT)								//256 FAT16 / 128 FAT32 entries per sector
			{
				temp_mx_cluster = temp_mx_cluster - FAT_1_FATS_PER_SECT;
				fat_address = fat_address + 1;										//Increment sector of FAT
			}
			FCD_FAT160_MX_Get_Buffer(fat_address);												//Read FAT sector
			old_mx_cluster = FAT_1_mx_cluster;

			Temp32.AsByte[0] = FCD_FAT160_Read_Byte_From_Buffer(temp_mx_cluster * FAT_1_SECT_ADDR_LEN);	//Extract data FAT_1_mx_cluster address
			Temp32.AsByte[1] = FCD_FAT160_Read_Byte_From_Buffer((temp_mx_cluster * FAT_1_SECT_ADDR_LEN) + 1);
			Temp32.AsByte[2] = 0;
			Temp32.AsByte[3] = 0;

			#if	(FAT_1_FAT_TYPE == 1 || FAT_1_FAT_TYPE == 2)
				if (FAT_1_mx_fat_system == 1)
				{
					Temp32.AsByte[2] = FCD_FAT160_Read_Byte_From_Buffer((temp_mx_cluster * FAT_1_SECT_ADDR_LEN) + 2);
					Temp32.AsByte[3] = FCD_FAT160_Read_Byte_From_Buffer((temp_mx_cluster * FAT_1_SECT_ADDR_LEN) + 3);
				}
			#endif

			FAT_1_mx_cluster = Temp32.AsLong;

			if (FAT_1_mx_cluster == 0 || FAT_1_mx_cluster >= FAT_1_NOT_ADDRESS_MARKER)							//If not an address
			{
				if (FAT_1_mx_cluster > FAT_1_MX_EOF_MARKER)
					retval = MX_ACK_EOF;											//End of file
				if (FAT_1_mx_cluster < FAT_1_MX_EOF_MARKER)
					retval = MX_ERR_RESERVED;										//Reserved FAT_1_mx_cluster
				if (FAT_1_mx_cluster == FAT_1_MX_EOF_MARKER)
					retval = MX_ERR_BAD;											//Bad FAT_1_mx_cluster
				if (FAT_1_mx_cluster == 0)
					retval = MX_ERR_FREE;											//Free FAT_1_mx_cluster - Fat Error

				FAT_1_mx_file_pointer[FAT_1_mx_file_idx] = FAT_1_mx_file_pointer[FAT_1_mx_file_idx] - 1;						//Restore address
				FAT_1_mx_cluster = old_mx_cluster;										//Restore FAT_1_mx_cluster
				FCD_FAT160_MX_Get_Buffer(FAT_1_mx_file_pointer[FAT_1_mx_file_idx]);									//Read sector
				return retval;
			}

			FAT_1_mx_file_pointer[FAT_1_mx_file_idx] = FAT_1_mx_data_start + ((FAT_1_mx_cluster - 2) * FAT_1_mx_sects_per_clust);			//Move to next sector in file   BR 06/10 was * 32
		}

		FAT_1_mx_file_sector[FAT_1_mx_file_idx] = FAT_1_mx_file_sector[FAT_1_mx_file_idx] + 1;										//Increment file sector

		return FCD_FAT160_MX_Get_Buffer(FAT_1_mx_file_pointer[FAT_1_mx_file_idx]);									//Read sector

}

static MX_UINT8 FCD_FAT160_MX_Send_Cmd(MX_UINT8 Cmd, MX_UINT32 Addr)
{
	
		MX_UINT8 i, RetVal;
		MX_Union32 Addr32;

		Addr32.AsLong = Addr;

		FC_CAL_Bit_Low ( FAT_1_MX_SPI_FAT_CS_PORT, FAT_1_MX_SPI_FAT_CS_PIN);		//CARD-Enabled

		FAT_1_SPI_Master_Byte(Cmd | 0x40);										//Send Command 0
		FAT_1_SPI_Master_Byte(Addr32.AsByte[3]);								//Arg3
		FAT_1_SPI_Master_Byte(Addr32.AsByte[2]);								//Arg2
		FAT_1_SPI_Master_Byte(Addr32.AsByte[1]);								//Arg1
		FAT_1_SPI_Master_Byte(Addr32.AsByte[0]);								//Arg0

		if(Cmd == SEND_IF_COND)	 					//it is compulsory to send correct CRC for CMD8 (CRC=0x87) & CMD0 (CRC=0x95)
		  	FAT_1_SPI_Master_Byte(0x87);    			//for remaining commands, CRC is ignored in SPI mode
		else
		  	FAT_1_SPI_Master_Byte(0x95);

		i = 0xfe;
		do
		{
			RetVal = FAT_1_SPI_Master_Byte(0xFF);		//Wait for response of 1
			if (RetVal != 0xff) break;
		} while ( --i > 0);

		if((RetVal == 0x00) && (Cmd == READ_OCR))  	//checking response of CMD58
		{
			i = FAT_1_SPI_Master_Byte(0xFF) & 0x40;    //first byte of the OCR register (bit 31:24)
			if(i == 0x40) FAT_1_mx_sdhc_flag = 1;  		//we need it to verify SDHC card
			else FAT_1_mx_sdhc_flag = 0;

			FAT_1_SPI_Master_Byte(0xFF); 				//remaining 3 bytes of the OCR register are ignored here
			FAT_1_SPI_Master_Byte(0xFF); 				//one can use these bytes to check power supply limits of SD
			FAT_1_SPI_Master_Byte(0xFF);
		}

		FAT_1_SPI_Master_Byte(0xFF);
		FC_CAL_Bit_High ( FAT_1_MX_SPI_FAT_CS_PORT, FAT_1_MX_SPI_FAT_CS_PIN);

		return (RetVal);

}

static void FCD_FAT160_Set_File_Index(MX_UINT8 File_Index)
{
	
		if (FAT_1_mx_file_idx < FAT_1_CONCURRENT_FILES)
			FAT_1_mx_file_idx = File_Index;

}

#include "C:\Program Files\Flowcode(AVR)\v5\CAL\includes.c"

//Macro implementations


int main()
{
	//Initialization
	MCUSR=0x00;


	//Interrupt initialization code
	
	//Setup FAT
	//Call Component Macro: Init_FAT()
	FCD_FAT160_Init_FAT();

	//Give FAT some time
	//Delay: 1 s
	delay_s(1);

	//Comment:
	//Create files on SD

	//Create file 0
	//Call Component Macro: Create_File("file0.txt")
	FCD_FAT160_Create_File("file0.txt", 9);

	//Create file 1
	//Call Component Macro: Create_File("file1.txt")
	FCD_FAT160_Create_File("file1.txt", 9);

	//Comment:
	//Open files and set index

	//Set index
	//Call Component Macro: Set_File_Index(0)
	FCD_FAT160_Set_File_Index(0);

	//Open file 0
	//Call Component Macro: Open_File("file0.txt")
	FCD_FAT160_Open_File("file0.txt", 9);

	//Set index
	//Call Component Macro: Set_File_Index(1)
	FCD_FAT160_Set_File_Index(1);

	//Open file 1
	//Call Component Macro: Open_File("file1.txt")
	FCD_FAT160_Open_File("file1.txt", 9);

	//Comment:
	//Write 1 to file 0, and 2 to file 1

	//Call Component Macro
	//Call Component Macro: Set_File_Index(0)
	FCD_FAT160_Set_File_Index(0);

	//Call Component Macro
	//Call Component Macro: Write_Byte_To_Buffer(0, 1)
	FCD_FAT160_Write_Byte_To_Buffer(0, 1);

	//Call Component Macro
	//Call Component Macro: Write_File_Sector()
	FCD_FAT160_Write_File_Sector();

	//Call Component Macro
	//Call Component Macro: Set_File_Index(1)
	FCD_FAT160_Set_File_Index(1);

	//Call Component Macro
	//Call Component Macro: Write_Byte_To_Buffer(0, 2)
	FCD_FAT160_Write_Byte_To_Buffer(0, 2);

	//Call Component Macro
	//Call Component Macro: Write_File_Sector()
	FCD_FAT160_Write_File_Sector();

	//Comment:
	//Display binary value on PortD of the first file

	//Call Component Macro
	//Call Component Macro: Set_File_Index(0)
	FCD_FAT160_Set_File_Index(0);

	//Call Component Macro
	//Call Component Macro: value=Read_Byte_From_Buffer(0)
	FCV_VALUE = FCD_FAT160_Read_Byte_From_Buffer(0);

	//Output
	//Output: value -> PORTD
	DDRD = 0xFF;
	PORTD = (FCV_VALUE);

	//Delay
	//Delay: 1 s
	delay_s(1);

	//Comment:
	//Display binary value on PortD of the second file

	//Call Component Macro
	//Call Component Macro: Set_File_Index(1)
	FCD_FAT160_Set_File_Index(1);

	//Call Component Macro
	//Call Component Macro: value=Read_Byte_From_Buffer(0)
	FCV_VALUE = FCD_FAT160_Read_Byte_From_Buffer(0);

	//Output
	//Output: value -> PORTD
	DDRD = 0xFF;
	PORTD = (FCV_VALUE);

	//Delay
	//Delay: 1 s
	delay_s(1);

	mainendloop: goto mainendloop;
}



