//************************************************************************************
//**  
//**  File name:     C:\Users\Robin\Documents\Flowcode\5. Data_Logger_Simple_Slow v2.c
//**  Generated by:  Flowcode v4.3.7.63
//**  Date:          Tuesday, August 10, 2010 17:35:32
//**  Licence:       Professional
//**  Registered to: Robin Cordell
//**  
//**  
//**  http://www.matrixmultimedia.com
//************************************************************************************


#define MX_PIC

//Defines for microcontroller
#define P18F4455
#define MX_EE
#define MX_EE_TYPE3
#define MX_EE_SIZE 256
#define MX_SPI
#define MX_SPI_BCB
#define MX_SPI_SDI 0
#define MX_SPI_SDO 7
#define MX_SPI_SCK 1
#define MX_UART
#define MX_UART_C
#define MX_UART_TX 6
#define MX_UART_RX 7
#define MX_I2C
#define MX_MI2C
#define MX_I2C_B
#define MX_I2C_SDA 0
#define MX_I2C_SCL 1
#define MX_PWM
#define MX_PWM_CNT 2
#define MX_PWM_TRIS1 trisc
#define MX_PWM_1 2
#define MX_PWM_TRIS2 trisc
#define MX_PWM_2 1
#define MX_PWM_TRIS2a trisb
#define MX_PWM_2a 3
#define MX_USB_TYPE1

//Functions
#define MX_CLK_SPEED 48000000
#ifdef _BOOSTC
#include <system.h>
#endif
#ifdef HI_TECH_C
#include <pic18.h>
#endif

//Configuration data
#ifdef _BOOSTC
#pragma DATA 0x300000, 0x24
#endif
#ifdef _HI_TECH_C
//__CONFIG(, );
#endif
#ifdef _BOOSTC
#pragma DATA 0x300001, 0xe
#endif
#ifdef _HI_TECH_C
__CONFIG(1, 0xe24);
#endif
#ifdef _BOOSTC
#pragma DATA 0x300002, 0x3e
#endif
#ifdef _HI_TECH_C
//__CONFIG(, );
#endif
#ifdef _BOOSTC
#pragma DATA 0x300003, 0x1e
#endif
#ifdef _HI_TECH_C
__CONFIG(2, 0x1e3e);
#endif
#ifdef _BOOSTC
#pragma DATA 0x300004, 0xff
#endif
#ifdef _HI_TECH_C
//__CONFIG(, );
#endif
#ifdef _BOOSTC
#pragma DATA 0x300005, 0x81
#endif
#ifdef _HI_TECH_C
__CONFIG(3, 0x81ff);
#endif
#ifdef _BOOSTC
#pragma DATA 0x300006, 0x81
#endif
#ifdef _HI_TECH_C
//__CONFIG(, );
#endif
#ifdef _BOOSTC
#pragma DATA 0x300007, 0xff
#endif
#ifdef _HI_TECH_C
__CONFIG(4, 0xff81);
#endif
#ifdef _BOOSTC
#pragma DATA 0x300008, 0xf
#endif
#ifdef _HI_TECH_C
//__CONFIG(, );
#endif
#ifdef _BOOSTC
#pragma DATA 0x300009, 0xc0
#endif
#ifdef _HI_TECH_C
__CONFIG(5, 0xc00f);
#endif
#ifdef _BOOSTC
#pragma DATA 0x30000a, 0xf
#endif
#ifdef _HI_TECH_C
//__CONFIG(, );
#endif
#ifdef _BOOSTC
#pragma DATA 0x30000b, 0xe0
#endif
#ifdef _HI_TECH_C
__CONFIG(6, 0xe00f);
#endif
#ifdef _BOOSTC
#pragma DATA 0x30000c, 0xf
#endif
#ifdef _HI_TECH_C
//__CONFIG(, );
#endif
#ifdef _BOOSTC
#pragma DATA 0x30000d, 0x40
#endif
#ifdef _HI_TECH_C
__CONFIG(7, 0x400f);
#endif

//Internal functions
#include "C:\Program Files\Matrix Multimedia\Flowcode V4\FCD\internals.h"

//Macro function declarations


//Variable declarations
#define FCSZ_FILENAME 20
#define FCSZ_FILESTRING 20
char FCV_RETVAL;
char FCV_CHAR;
char FCV_FILENAME[FCSZ_FILENAME];
char FCV_COUNT;
short FCV_ADC_VAL;
char FCV_FILESTRING[FCSZ_FILESTRING];

char FCLV_LOOP1;

//Defines:

/**** Macro Substitutions ****
portb = D1 Port
trisb = D1 Data Direction
portb = D2 Port
trisb = D2 Data Direction
portb = D3 Port
trisb = D3 Data Direction
portb = D4 Port
trisb = D4 Data Direction
portb = RS Port
trisb = RS Data Direction
portb = E Port
trisb = E Data Direction
0 = Data 1_Pin
1 = Data 2 Pin
2 = Data 3 Pin
3 = Data 4 Pin
4 = RS Pin
5 = Enable Pin
LCD_265444 = Unique Component Reference Number
2 = Row Count
16 = Column Count
******************************/

	//component connections
	#define LCD_265444_PORT0    portb
	#define LCD_265444_TRIS0    trisb
	#define LCD_265444_PORT1    portb
	#define LCD_265444_TRIS1    trisb
	#define LCD_265444_PORT2    portb
	#define LCD_265444_TRIS2    trisb
	#define LCD_265444_PORT3    portb
	#define LCD_265444_TRIS3    trisb
	#define LCD_265444_PORT4    portb
	#define LCD_265444_TRIS4    trisb
	#define LCD_265444_PORT5    portb
	#define LCD_265444_TRIS5    trisb
	#define LCD_265444_BIT0    	0
	#define LCD_265444_BIT1    	1
	#define LCD_265444_BIT2    	2
	#define LCD_265444_BIT3    	3
	#define LCD_265444_RS      	4
	#define LCD_265444_E       	5
	#define LCD_265444_ROWCNT	2
	#define LCD_265444_COLCNT	16

	#ifdef _BOOSTC
	  #define LCD_265444_DELAY   delay_10us(10)
	#endif
	#ifdef _C2C_
	  #define LCD_265444_DELAY   delay_us(100)
	#endif
	#ifdef HI_TECH_C
	  #define LCD_265444_DELAY   __delay_us(120)
	#endif
	#ifndef LCD_265444_DELAY
	  #define LCD_265444_DELAY   delay_us(100)
	#endif




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

void FCD_LCDDisplay0_RawSend(char in, char mask);
void FCD_LCDDisplay0_Start();
void FCD_LCDDisplay0_Clear();
void FCD_LCDDisplay0_PrintASCII(char Character);
void FCD_LCDDisplay0_Command(char in);
void FCD_LCDDisplay0_Cursor(char x, char y);
void FCD_LCDDisplay0_PrintNumber(short Number);
void FCD_LCDDisplay0_PrintString(char* String, char MSZ_String);
void FCD_LCDDisplay0_ScrollDisplay(char Direction, char Num_Positions);
void FCD_LCDDisplay0_ClearLine(char Line);
void FCD_LCDDisplay0_RAM_Write(char nIdx, char d0, char d1, char d2, char d3, char d4, char d5, char d6, char d7);
//Defines:

/**** Macro Substitutions ****
0 = Which ADC Channel
40 = Acquisition time
3 = Conversion Speed
0 = VRef+ Option
500 = VRef Voltage x 0.01V
******************************/




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

void FCD_ADC0_SampleADC();
char FCD_ADC0_ReadAsByte();
short FCD_ADC0_ReadAsInt();
float FCD_ADC0_ReadAsVoltage();
void FCD_ADC0_ReadAsString(char* FCR_RETVAL, char FCR_RETVAL_SIZE);
//Defines:

/**** Macro Substitutions ****
porta = Card Port Register
trisa = Card Data Direction Register
2 = Chip Selection Pin
3 = Serial Clock
4 = Serial Data In
5 = Serial Data Out
15626 = File Creation Time
35952 = File Creation Date
0 = FAT System Type - FAT16 Only
0 = Unused
0 = Hardware SPI - 0 software, 1 hardware
******************************/

	//Flowcode Defines
	#define MX_CARD_PORT 			porta
	#define MX_CARD_TRIS 			trisa
	#define MX_CARD_CS 				2
	#define MX_CARD_SCK 			3
	#define MX_CARD_SDI 			4
	#define MX_CARD_SDO 			5
	#define MX_FILE_CREATEDATE		15626
	#define MX_FILE_CREATETIME		35952
	#define MX_FAT_SYST				0
	#define MX_EXT_NAME				0
	#define MX_HW_SPI				0
	#define MX_FAT_TYPE				0//0		//0-FAT16(FAT) / 1-FAT32 / 2-FAT16&32

	#include <string.h>

	//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

	//Global Variables
	char mx_card_bufferl[256];				//512-Byte Global Buffer Variables
	char mx_card_bufferh[256];
	char mx_name_ext[12];					//11 byte fat file name: 8 char filename + 3 char extension
	char mx_file_entry;						//Directory entry of file
	char mx_sects_per_clust;				//Number of sectors per cluster    - Added BR 06/10
	unsigned int mx_root_sectors = 0;		//Number of sectors in the root directory
	unsigned int mx_fat_size = 0;			//FAT size in sectors
	unsigned long mx_fat_start = 0;			//Start address of FAT tables
	unsigned long mx_root_start = 0;		//Start address of root directory
	unsigned long mx_data_start = 0;		//Start address of the data
	unsigned long mx_file_size = 0;			//Size of file in bytes
	unsigned long mx_file_address = 0; 		//Start address of File
	unsigned long mx_file_sector = 1;		//Current sector of file
	unsigned long mx_folder_size = 0;		//Folder size in sectors
	unsigned long mx_folder_start = 0;		//Start address of Folder
	unsigned long mx_current_address = 0;	//Current address loaded in memory

	#if (MX_FAT_TYPE == 0)
		unsigned int mx_cluster = 2;		//Current data mx_cluster in the memory
		#define SECT_ADDR_LEN			2
		#define FATS_PER_SECT			(512 / 2)	//2 bytes per fat record
		#define NOT_ADDRESS_MARKER		0xFFF0
		#define MX_EOF_MARKER			0xFFF7
	#endif
	#if (MX_FAT_TYPE == 1)
		unsigned long mx_cluster = 2;		//Current data mx_cluster in the memory
		#define mx_fat_system  			1
		#define SECT_ADDR_LEN			4
		#define FATS_PER_SECT			(512 / 4)	//4 bytes per fat record
		#define NOT_ADDRESS_MARKER		0x0FFFFFF0
		#define MX_EOF_MARKER			0x0FFFFFF7
	#endif
	#if (MX_FAT_TYPE == 2)
		unsigned long mx_cluster = 2;		//Current data mx_cluster in the memory
		char mx_fat_system;						//Type of FAT file system in use on disk     - Added BR 07/10
		char SECT_ADDR_LEN;						//Defines become variables
		unsigned int FATS_PER_SECT;
		unsigned long NOT_ADDRESS_MARKER;
		unsigned long MX_EOF_MARKER;
	#endif




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

char FCD_FAT160_Init_FAT();
char FCD_FAT160_Open_File(char* File_Name, char MSZ_File_Name);
char FCD_FAT160_Read_File_Sector();
short FCD_FAT160_Read_File_Length();
char FCD_FAT160_Move_To_Next_File_Sector(char Force_Next_Sector);
char FCD_FAT160_Append_String_To_File(char* String, char MSZ_String);
char FCD_FAT160_Write_File_Sector();
char FCD_FAT160_Create_File(char* File_Name, char MSZ_File_Name);
char FCD_FAT160_Delete_File(char* File_Name, char MSZ_File_Name);
void FCD_FAT160_Write_Byte_To_Buffer(short Address, char Data);
char FCD_FAT160_Read_Byte_From_Buffer(short Address);
char FCD_FAT160_Open_Folder(char* Folder_Name, char MSZ_Folder_Name);
short FCD_FAT160_Scan_Current_Folder(short Current_Idx, char Scan_Type);
char FCD_FAT160_Read_Byte_From_Scan(char idx);
char FCD_FAT160_MX_SPI_BYTE(char shift);
char FCD_FAT160_MX_Init_Card();
char FCD_FAT160_MX_Send_Buffer(long address);
char FCD_FAT160_MX_Get_Buffer(long address);
void FCD_FAT160_MX_Format_File_String(char* File_Name, char MSZ_File_Name);
void FCD_FAT160_MX_Add_Sector_To_File();
void FCD_FAT160_MX_Clear_Buffer();
char FCD_FAT160_Read_Next_File_Sector();



//LCDDisplay(0): //Macro implementations


void FCD_LCDDisplay0_RawSend(char in, char mask)
{
		unsigned char pt;

		clear_bit(LCD_265444_PORT0, LCD_265444_BIT0);
		clear_bit(LCD_265444_PORT1, LCD_265444_BIT1);
		clear_bit(LCD_265444_PORT2, LCD_265444_BIT2);
		clear_bit(LCD_265444_PORT3, LCD_265444_BIT3);
		clear_bit(LCD_265444_PORT4, LCD_265444_RS);
		clear_bit(LCD_265444_PORT5, LCD_265444_E);
		pt = ((in >> 4) & 0x0f);
		if (pt & 0x01)
		    set_bit(LCD_265444_PORT0, LCD_265444_BIT0);
		if (pt & 0x02)
		    set_bit(LCD_265444_PORT1, LCD_265444_BIT1);
		if (pt & 0x04)
		    set_bit(LCD_265444_PORT2, LCD_265444_BIT2);
		if (pt & 0x08)
		    set_bit(LCD_265444_PORT3, LCD_265444_BIT3);
		if (mask)
		    set_bit(LCD_265444_PORT4, LCD_265444_RS);
		LCD_265444_DELAY;
		set_bit (LCD_265444_PORT5, LCD_265444_E);
		LCD_265444_DELAY;
		clear_bit (LCD_265444_PORT5, LCD_265444_E);
		pt = (in & 0x0f);
		LCD_265444_DELAY;
		clear_bit(LCD_265444_PORT0, LCD_265444_BIT0);
		clear_bit(LCD_265444_PORT1, LCD_265444_BIT1);
		clear_bit(LCD_265444_PORT2, LCD_265444_BIT2);
		clear_bit(LCD_265444_PORT3, LCD_265444_BIT3);
		clear_bit(LCD_265444_PORT4, LCD_265444_RS);
		clear_bit(LCD_265444_PORT5, LCD_265444_E);
		if (pt & 0x01)
		    set_bit(LCD_265444_PORT0, LCD_265444_BIT0);
		if (pt & 0x02)
		    set_bit(LCD_265444_PORT1, LCD_265444_BIT1);
		if (pt & 0x04)
		    set_bit(LCD_265444_PORT2, LCD_265444_BIT2);
		if (pt & 0x08)
		    set_bit(LCD_265444_PORT3, LCD_265444_BIT3);
		if (mask)
		    set_bit(LCD_265444_PORT4, LCD_265444_RS);
		LCD_265444_DELAY;
		set_bit (LCD_265444_PORT5, LCD_265444_E);
		LCD_265444_DELAY;
		clear_bit (LCD_265444_PORT5, LCD_265444_E);
		LCD_265444_DELAY;
}

void FCD_LCDDisplay0_Start()
{
	
		clear_bit(LCD_265444_TRIS0, LCD_265444_BIT0);
		clear_bit(LCD_265444_TRIS1, LCD_265444_BIT1);
		clear_bit(LCD_265444_TRIS2, LCD_265444_BIT2);
		clear_bit(LCD_265444_TRIS3, LCD_265444_BIT3);
		clear_bit(LCD_265444_TRIS4, LCD_265444_RS);
		clear_bit(LCD_265444_TRIS5, LCD_265444_E);

		Wdt_Delay_Ms(12);

		FCD_LCDDisplay0_RawSend(0x33, 0);
		Wdt_Delay_Ms(2);
		FCD_LCDDisplay0_RawSend(0x33, 0);
		Wdt_Delay_Ms(2);
		FCD_LCDDisplay0_RawSend(0x32, 0);
		Wdt_Delay_Ms(2);
		FCD_LCDDisplay0_RawSend(0x2c, 0);
		Wdt_Delay_Ms(2);
		FCD_LCDDisplay0_RawSend(0x06, 0);
		Wdt_Delay_Ms(2);
		FCD_LCDDisplay0_RawSend(0x0c, 0);
		Wdt_Delay_Ms(2);

		//clear the display
		FCD_LCDDisplay0_RawSend(0x01, 0);
		Wdt_Delay_Ms(2);
		FCD_LCDDisplay0_RawSend(0x02, 0);
		Wdt_Delay_Ms(2);

}

void FCD_LCDDisplay0_Clear()
{
	
		FCD_LCDDisplay0_RawSend(0x01, 0);
		Wdt_Delay_Ms(2);
		FCD_LCDDisplay0_RawSend(0x02, 0);
		Wdt_Delay_Ms(2);

}

void FCD_LCDDisplay0_PrintASCII(char Character)
{
	
		FCD_LCDDisplay0_RawSend(Character, 0x10);

}

void FCD_LCDDisplay0_Command(char in)
{
	
		FCD_LCDDisplay0_RawSend(in, 0);
		Wdt_Delay_Ms(2);

}

void FCD_LCDDisplay0_Cursor(char x, char y)
{
	
	  #if (LCD_265444_ROWCNT == 1)
	    y=0x80;
	  #endif

	  #if (LCD_265444_ROWCNT == 2)
		if (y==0)
			y=0x80;
		else
			y=0xc0;
	  #endif

	  #if (LCD_265444_ROWCNT == 4)
		if (y==0)
			y=0x80;
		else if (y==1)
			y=0xc0;

		#if (LCD_265444_COLCNT == 16)
			else if (y==2)
				y=0x90;
			else
				y=0xd0;
		#endif

		#if (LCD_265444_COLCNT == 20)
			else if (y==2)
				y=0x94;
			else
				y=0xd4;
		#endif
	  #endif

		FCD_LCDDisplay0_RawSend(y+x, 0);
		Wdt_Delay_Ms(2);

}

void FCD_LCDDisplay0_PrintNumber(short Number)
{
	
		short tmp_int;
		char tmp_byte;
		if (Number < 0)
		{
			FCD_LCDDisplay0_RawSend('-', 0x10);
			Number = 0 - Number;
		}

		tmp_int = Number;
		if (Number >= 10000)
		{
			tmp_byte = tmp_int / 10000;
			FCD_LCDDisplay0_RawSend('0' + tmp_byte, 0x10);

			while (tmp_byte > 0)
			{
				tmp_int = tmp_int - 10000;
				tmp_byte--;
			}
		}
		if (Number >= 1000)
		{
			tmp_byte = tmp_int / 1000;
			FCD_LCDDisplay0_RawSend('0' + tmp_byte, 0x10);

			while (tmp_byte > 0)
			{
				tmp_int = tmp_int - 1000;
				tmp_byte--;
			}
		}
		if (Number >= 100)
		{
			tmp_byte = tmp_int / 100;
			FCD_LCDDisplay0_RawSend('0' + tmp_byte, 0x10);

			while (tmp_byte > 0)
			{
				tmp_int = tmp_int - 100;
				tmp_byte--;
			}
		}
		if (Number >= 10)
		{
			tmp_byte = tmp_int / 10;
			FCD_LCDDisplay0_RawSend('0' + tmp_byte, 0x10);

			while (tmp_byte > 0)
			{
				tmp_int = tmp_int - 10;
				tmp_byte--;
			}
		}
		FCD_LCDDisplay0_RawSend('0' + tmp_int, 0x10);

}

void FCD_LCDDisplay0_PrintString(char* String, char MSZ_String)
{
	
		char idx = 0;

		for (idx=0; idx<MSZ_String; idx++)
		{
			#ifdef _BOOSTC
				if (String[idx] == 0)
				{
					break;
				}
				FCD_LCDDisplay0_RawSend(String[idx], 0x10);
			#endif

			#ifdef HI_TECH_C
				if (*String == 0)
				{
					break;
				}
				FCD_LCDDisplay0_RawSend(*String, 0x10);
				String++;
			#endif
		}

}

void FCD_LCDDisplay0_ScrollDisplay(char Direction, char Num_Positions)
{
	
		char cmd = 0;
		char count;

		//Choose the direction
		switch (Direction)
		{
			case 0:
			case 'l':
			case 'L':

				cmd = 0x18;
				break;

			case 1:
			case 'r':
			case 'R':

				cmd = 0x1C;
				break;

			default:
				break;
		}

		//If direction accepted then scroll the specified amount
		if (cmd)
		{
			for (count = 0; count < Num_Positions; count++)
				FCD_LCDDisplay0_Command(cmd);
		}

}

void FCD_LCDDisplay0_ClearLine(char Line)
{
	
		char count;
		char rowcount;

		//Define number of columns per line
		#if (LCD_265444_ROWCNT == 1)
			rowcount=80;
		#endif

		#if (LCD_265444_ROWCNT == 2)
			rowcount=40;
		#endif

		#if (LCD_265444_ROWCNT == 4)
			#if (LCD_265444_COLCNT == 16)
				rowcount=16;
			#endif
			#if (LCD_265444_COLCNT == 20)
				rowcount=20;
			#endif
		#endif

		//Start at beginning of the line
		FCD_LCDDisplay0_Cursor (0, Line);

		//Send out spaces to clear line
		for (count = 0; count < rowcount; count++)
			FCD_LCDDisplay0_RawSend(' ', 0x10);

		//Move back to the beginning of the line.
		FCD_LCDDisplay0_Cursor (0, Line);

}

void FCD_LCDDisplay0_RAM_Write(char nIdx, char d0, char d1, char d2, char d3, char d4, char d5, char d6, char d7)
{
	   //set CGRAM address
	   FCD_LCDDisplay0_RawSend(64 + (nIdx << 3), 0);
	   delay_ms(2);

	   //write CGRAM data
	   FCD_LCDDisplay0_RawSend(d0, 0x10);
	   FCD_LCDDisplay0_RawSend(d1, 0x10);
	   FCD_LCDDisplay0_RawSend(d2, 0x10);
	   FCD_LCDDisplay0_RawSend(d3, 0x10);
	   FCD_LCDDisplay0_RawSend(d4, 0x10);
	   FCD_LCDDisplay0_RawSend(d5, 0x10);
	   FCD_LCDDisplay0_RawSend(d6, 0x10);
	   FCD_LCDDisplay0_RawSend(d7, 0x10);

	   //Clear the display
	   FCD_LCDDisplay0_RawSend(0x01, 0);
	   delay_ms(2);
	   FCD_LCDDisplay0_RawSend(0x02, 0);
	   delay_ms(2);
}



//ADC(0): //Macro implementations


void FCD_ADC0_SampleADC()
{
	
	/*******Supported Devices******************************************************************
	// 18F2220, 18F2221, 18F2320, 18F2321, 18F24J10, 18F2410, 18F2420, 18F2423, 18F2450,
	// 18F2455, 18F2480, 18F25J10, 18F2510, 18F2515, 18F2520, 18F2523, 18F2525, 18F2550,
	// 18F2580, 18F2585, 18F2610, 18F2620, 18F2680, 18F4220, 18F4221, 18F4320, 18F4321,
	// 18F44J10, 18F4410, 18F4420, 18F4423, 18F4450, 18F4455, 18F4480, 18F45J10, 18F4510,
	// 18F4515, 18F4520, 18F4523, 18F4525, 18F4550, 18F4580, 18F4585, 18F4610, 18F4620,
	// 18F4680, 18F4682, 18F4685
	******************************************************************************************/

		#define MX_ADC_CHANNEL		0
		#define MX_ADC_SAMP_TIME 	40
		#define MX_ADC_CONV_SP		3
		#define MX_ADC_VREF_OPT		0

		//set up ADC conversion
		char old_tris, cnt;
		adcon2 = MX_ADC_CONV_SP & 0x07;

		//find appropriate bit
		#if (MX_ADC_CHANNEL == 0)
			#define MX_ADC_TRIS_REG  trisa
			#define MX_ADC_TRIS_MSK  0x01
			adcon1 = 0x0E;
		#endif
		#if (MX_ADC_CHANNEL == 1)
			#define MX_ADC_TRIS_REG  trisa
			#define MX_ADC_TRIS_MSK  0x02
			adcon1 = 0x0D;
		#endif
		#if (MX_ADC_CHANNEL == 2)
			#define MX_ADC_TRIS_REG  trisa
			#define MX_ADC_TRIS_MSK  0x04
			adcon1 = 0x0C;
		#endif
		#if (MX_ADC_CHANNEL == 3)
			#define MX_ADC_TRIS_REG  trisa
			#define MX_ADC_TRIS_MSK  0x08
			adcon1 = 0x0B;
			#if (MX_ADC_VREF_OPT != 0)
				#ifdef _BOOSTC
					#pragma error "Target device is currently using AN3 for VREF+"
				#endif
				#ifdef HI_TECH_C
					#error Target device is currently using AN3 for VREF+
				#endif
			#endif
		#endif
		#if (MX_ADC_CHANNEL == 4)
			#define MX_ADC_TRIS_REG  trisa
			#define MX_ADC_TRIS_MSK  0x20
			adcon1 = 0x0A;
		#endif
		#if (MX_ADC_CHANNEL == 5)
			#define MX_ADC_TRIS_REG  trise
			#define MX_ADC_TRIS_MSK  0x01
			adcon1 = 0x09;
		#endif
		#if (MX_ADC_CHANNEL == 6)
			#define MX_ADC_TRIS_REG  trise
			#define MX_ADC_TRIS_MSK  0x02
			adcon1 = 0x08;
		#endif
		#if (MX_ADC_CHANNEL == 7)
			#define MX_ADC_TRIS_REG  trise
			#define MX_ADC_TRIS_MSK  0x04
			adcon1 = 0x07;
		#endif
		#if (MX_ADC_CHANNEL == 8)
			#define MX_ADC_TRIS_REG  trisb
			#define MX_ADC_TRIS_MSK  0x02
			adcon1 = 0x06;
		#endif
		#if (MX_ADC_CHANNEL == 9)
			#define MX_ADC_TRIS_REG  trisb
			#define MX_ADC_TRIS_MSK  0x10
			adcon1 = 0x05;
		#endif
		#if (MX_ADC_CHANNEL == 10)
			#define MX_ADC_TRIS_REG  trisb
			#define MX_ADC_TRIS_MSK  0x02
			adcon1 = 0x04;
		#endif
		#if (MX_ADC_CHANNEL == 11)
			#define MX_ADC_TRIS_REG  trisb
			#define MX_ADC_TRIS_MSK  0x10
			adcon1 = 0x03;
		#endif
		#if (MX_ADC_CHANNEL == 12)
			#define MX_ADC_TRIS_REG  trisb
			#define MX_ADC_TRIS_MSK  0x01
			adcon1 = 0x02;
		#endif

		//sanity check
		#ifndef MX_ADC_TRIS_REG
			#ifdef _BOOSTC
				#pragma error "ADC Type 13 conversion code error - please contact technical support"
			#endif
			#ifdef HI_TECH_C
				#error ADC Type 13 conversion code error - please contact technical support
			#endif
		#endif

		//assign VREF functionality
		#if (MX_ADC_VREF_OPT != 0)
			st_bit(adcon1, VCFG0);
		#endif

		//store old tris value, and set the i/o pin as an input
		old_tris = MX_ADC_TRIS_REG;
		MX_ADC_TRIS_REG = MX_ADC_TRIS_REG | MX_ADC_TRIS_MSK;

		//turn ADC on
		adcon0 = 0x01 | (MX_ADC_CHANNEL << 2);

		//wait the acquisition time
		cnt = 0;
		while (cnt < MX_ADC_SAMP_TIME) cnt++;

		//begin conversion and wait until it has finished
		adcon0 = adcon0 | 0x02;
		while (adcon0 & 0x02);

		//restore old tris value, and reset adc registers
		MX_ADC_TRIS_REG = old_tris;
		adcon1 = 0x0f;
		adcon0 = 0x00;

		#undef MX_ADC_TRIS_REG
		#undef MX_ADC_TRIS_MSK
		#undef MX_ADC_SAMP_TIME
		#undef MX_ADC_CHANNEL
		#undef MX_ADC_CONV_SP
		#undef MX_ADC_VREF_OPT

}

char FCD_ADC0_ReadAsByte()
{
	
		FCD_ADC0_SampleADC();

		return adresh;

}

short FCD_ADC0_ReadAsInt()
{
	
		short iRetVal;

		FCD_ADC0_SampleADC();

		iRetVal = (adresh << 2);
		iRetVal = iRetVal | (adresl >> 6);

		return (iRetVal);

}

float FCD_ADC0_ReadAsVoltage()
{
	

		int iSample;
		float fSample, fVoltage, fVperDiv;

		#define MX_ADC_VREF_V		500

		iSample = FCD_ADC0_ReadAsInt();											//Read as 10-bit Integer

		#ifdef _BOOSTC
			fVoltage = float32_from_int32(MX_ADC_VREF_V);					//Convert reference voltage count to floating point (0 - 500 x 10mV)
			fVoltage = float32_mul(fVoltage, 0.01);							//Convert reference voltage count to actual voltage (0 - 5)
			fVperDiv = float32_mul(fVoltage, 0.000976);						//Convert actual voltage to voltage per division (VRef / 1024)
			fSample = float32_from_int32(iSample);							//Convert to floating point variable
			fVoltage = float32_mul(fSample, fVperDiv);						//Calculate floating point voltage
		#endif

		#ifdef HI_TECH_C
			fVoltage = MX_ADC_VREF_V;										//Convert reference voltage count to floating point (0 - 500 x 10mV)
			fVoltage = fVoltage * 0.01;										//Convert reference voltage count to actual voltage (0 - 5)
			fVperDiv = fVoltage * 0.000976;									//Convert actual voltage to voltage per division (VRef / 1024)
			fSample = iSample;												//Convert to floating point variable
			fVoltage = fSample * fVperDiv;									//Calculate floating point voltage
		#endif

		#undef MX_ADC_VREF_V
		return (fVoltage);

}

void FCD_ADC0_ReadAsString(char* FCR_RETVAL, char FCR_RETVAL_SIZE)
{
	
		float fVoltage;

		fVoltage = FCD_ADC0_ReadAsVoltage();
		FCI_FLOAT_TO_STRING(fVoltage, 2, FCR_RETVAL, FCR_RETVAL_SIZE);	//Convert to String

}



//FAT16(0): //Macro implementations


char FCD_FAT160_Init_FAT()
{
		char retval;
		char i, num_fats;
		unsigned int bytes_per_sect = 0;
		unsigned int reserved_sectors;
		unsigned long partition_start = 0;  //Start address of the partition
		unsigned long root_size;			//Number of 32 byte root entries.

		retval = FCD_FAT160_MX_Init_Card();											//Startup Card
		if (retval)
			return(retval);													//Startup error or no card
		retval = FCD_FAT160_MX_Get_Buffer(0);											//Read Master Boot Record if available
		if (retval)
			return(retval);

		while (bytes_per_sect == 0)											//Search for valid partition table
		{
			partition_start = FCD_FAT160_Read_Byte_From_Buffer(0x01C9);								//Read start address of partition
			partition_start = (partition_start << 8) | FCD_FAT160_Read_Byte_From_Buffer(0x01C8);
			partition_start = (partition_start << 8) | FCD_FAT160_Read_Byte_From_Buffer(0x01C7);
			partition_start = (partition_start << 8) | FCD_FAT160_Read_Byte_From_Buffer(0x01C6);

			retval = FCD_FAT160_MX_Get_Buffer(partition_start);										//Read Start of Partition (should also work for disks with no MBR or extended partitions)

			bytes_per_sect = FCD_FAT160_Read_Byte_From_Buffer(0x0B);									//Bytes per sector - normally 512
			bytes_per_sect = bytes_per_sect | ( FCD_FAT160_Read_Byte_From_Buffer(0x0C) << 8);
		}

		if (bytes_per_sect != 512)															//BR Added 06/10 - Confirm that sector is correct size
			return MX_ERR_SECTBYTES;

		mx_sects_per_clust = FCD_FAT160_Read_Byte_From_Buffer(0x0D);									//Read number of sectors per mx_cluster

		reserved_sectors = FCD_FAT160_Read_Byte_From_Buffer(0x0E);										//Number of reserved sectors
		reserved_sectors = reserved_sectors | ( FCD_FAT160_Read_Byte_From_Buffer(0x0F) << 8);

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

		#if (MX_FAT_TYPE == 2)
			if ( FCD_FAT160_Read_Byte_From_Buffer(0x55) == '3')											//Is this a FAT32 card?
			{
				mx_fat_system = 1;
				SECT_ADDR_LEN = 4;
				FATS_PER_SECT = 128;
				NOT_ADDRESS_MARKER = 0x0FFFFFF0;
				MX_EOF_MARKER = 0x0FFFFFF7;
			}
			else
			{
				mx_fat_system = 0;
				SECT_ADDR_LEN = 2;
				FATS_PER_SECT = 256;
				NOT_ADDRESS_MARKER = 0xFFF0;
				MX_EOF_MARKER = 0xFFF7;
			}
		#endif

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

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

			root_size = FCD_FAT160_Read_Byte_From_Buffer(0x11);										//Size of root directory x 32 byte file/directory entries
			root_size = root_size | ( FCD_FAT160_Read_Byte_From_Buffer(0x12) << 8);

			if(root_size == 0)																//if root size not defined here
			{
				root_size = FCD_FAT160_Read_Byte_From_Buffer(0x24);									//Size of root directory x 32 byte file/directory entries
				root_size = root_size | ( FCD_FAT160_Read_Byte_From_Buffer(0x25) << 8);
				root_size = root_size | ((long)  FCD_FAT160_Read_Byte_From_Buffer(0x26) << 16);
				root_size = root_size | ((long)  FCD_FAT160_Read_Byte_From_Buffer(0x27) << 24);
			}
			mx_root_sectors = (root_size * 32) / 512;										//Number of sectors in the root directory
			mx_fat_size = FCD_FAT160_Read_Byte_From_Buffer(0x16);										//FAT size in sectors
			mx_fat_size = mx_fat_size | ( FCD_FAT160_Read_Byte_From_Buffer(0x17) << 8);
			mx_root_start = mx_fat_start + (num_fats * mx_fat_size);						//start of the root directory in sectors
			mx_data_start = mx_root_start + mx_root_sectors;								//start of the data mx_clusters in sectors

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

			mx_root_sectors = mx_sects_per_clust;

			mx_fat_size = FCD_FAT160_Read_Byte_From_Buffer(0x24);											//FAT size in sectors
			mx_fat_size = mx_fat_size | ( FCD_FAT160_Read_Byte_From_Buffer(0x25) << 8);
			mx_fat_size = mx_fat_size | ( FCD_FAT160_Read_Byte_From_Buffer(0x26) << 16);
			mx_fat_size = mx_fat_size | ( FCD_FAT160_Read_Byte_From_Buffer(0x27) << 24);

			root_size = FCD_FAT160_Read_Byte_From_Buffer(0x2C);										//first cluster address of root directory
			root_size = root_size | ( FCD_FAT160_Read_Byte_From_Buffer(0x2D) << 8);
			root_size = root_size | ((long)  FCD_FAT160_Read_Byte_From_Buffer(0x2E) << 16);
			root_size = root_size | ((long)  FCD_FAT160_Read_Byte_From_Buffer(0x2F) << 24);

			mx_data_start = mx_fat_start + (num_fats * mx_fat_size);						//start of the root directory in sectors
			mx_root_start = mx_data_start + ((root_size - 2) * mx_sects_per_clust);			//Move to sector containing start of file

		#endif
		#if (MX_FAT_TYPE == 2)
			if (mx_fat_system == 0)																//FAT32 uses normal folder cluster for root
			{
				root_size = FCD_FAT160_Read_Byte_From_Buffer(0x11);										//Size of root directory x 32 byte file/directory entries
				root_size = root_size | ( FCD_FAT160_Read_Byte_From_Buffer(0x12) << 8);

				if(root_size == 0)																//if root size not defined here
				{
					root_size = FCD_FAT160_Read_Byte_From_Buffer(0x24);									//Size of root directory x 32 byte file/directory entries
					root_size = root_size | ( FCD_FAT160_Read_Byte_From_Buffer(0x25) << 8);
					root_size = root_size | ((long)  FCD_FAT160_Read_Byte_From_Buffer(0x26) << 16);
					root_size = root_size | ((long)  FCD_FAT160_Read_Byte_From_Buffer(0x27) << 24);
				}
				mx_root_sectors = (root_size * 32) / 512;										//Number of sectors in the root directory
				mx_fat_size = FCD_FAT160_Read_Byte_From_Buffer(0x16);										//FAT size in sectors
				mx_fat_size = mx_fat_size | ( FCD_FAT160_Read_Byte_From_Buffer(0x17) << 8);
				mx_root_start = mx_fat_start + (num_fats * mx_fat_size);						//start of the root directory in sectors
				mx_data_start = mx_root_start + mx_root_sectors;								//start of the data mx_clusters in sectors

			}
			if (mx_fat_system == 1)																//FAT32 uses normal folder cluster for root
			{
				mx_root_sectors = mx_sects_per_clust;

				mx_fat_size = FCD_FAT160_Read_Byte_From_Buffer(0x24);											//FAT size in sectors
				mx_fat_size = mx_fat_size | ( FCD_FAT160_Read_Byte_From_Buffer(0x25) << 8);
				mx_fat_size = mx_fat_size | ( FCD_FAT160_Read_Byte_From_Buffer(0x26) << 16);
				mx_fat_size = mx_fat_size | ( FCD_FAT160_Read_Byte_From_Buffer(0x27) << 24);

				root_size = FCD_FAT160_Read_Byte_From_Buffer(0x2C);										//first cluster address of root directory
				root_size = root_size | ( FCD_FAT160_Read_Byte_From_Buffer(0x2D) << 8);
				root_size = root_size | ((long)  FCD_FAT160_Read_Byte_From_Buffer(0x2E) << 16);
				root_size = root_size | ((long)  FCD_FAT160_Read_Byte_From_Buffer(0x2F) << 24);

				mx_data_start = mx_fat_start + (num_fats * mx_fat_size);						//start of the root directory in sectors
				mx_root_start = mx_data_start + ((root_size - 2) * mx_sects_per_clust);			//Move to sector containing start of file
			}
		#endif

		mx_folder_size = mx_root_sectors;
		mx_folder_start = mx_root_start;

		return retval;
}

char FCD_FAT160_Open_File(char* File_Name, char MSZ_File_Name)
{
	
		char i;
		char name_comp[11];
		char address[4];
		int idx_fat;
		unsigned int scount;
		#if (MX_FAT_TYPE == 0)
			unsigned int fat_pointer = 0xFFFF;
		#endif
		#if (MX_FAT_TYPE == 1)
			unsigned long fat_pointer = 0x0FFFFFFF;
		#endif
		#if (MX_FAT_TYPE == 2)
			unsigned long fat_pointer;
			if (mx_fat_system == 0)
				fat_pointer = 0xFFFF;
			else fat_pointer = 0x0FFFFFFF;
		#endif
		unsigned long fat_address;

		FCD_FAT160_MX_Format_File_String(File_Name, MSZ_File_Name);							//Convert filename to 8.3 format
		scount = 0;
		mx_current_address = mx_folder_start;										//Move to start of root
		while (scount < mx_folder_size)
		{
			FCD_FAT160_MX_Get_Buffer(mx_current_address);										//Read sector of root directory
			for(i=0;i<16;i++)														//16 file or directory references per sector
			{
				name_comp[0] = FCD_FAT160_Read_Byte_From_Buffer(0 + (i*32));					//Move DOS 8.3 Filename into 2nd comparison buffer
				name_comp[1] = FCD_FAT160_Read_Byte_From_Buffer(1 + (i*32));
				name_comp[2] = FCD_FAT160_Read_Byte_From_Buffer(2 + (i*32));
				name_comp[3] = FCD_FAT160_Read_Byte_From_Buffer(3 + (i*32));
				name_comp[4] = FCD_FAT160_Read_Byte_From_Buffer(4 + (i*32));
				name_comp[5] = FCD_FAT160_Read_Byte_From_Buffer(5 + (i*32));
				name_comp[6] = FCD_FAT160_Read_Byte_From_Buffer(6 + (i*32));
				name_comp[7] = FCD_FAT160_Read_Byte_From_Buffer(7 + (i*32));
				name_comp[8] = FCD_FAT160_Read_Byte_From_Buffer(8 + (i*32));
				name_comp[9] = FCD_FAT160_Read_Byte_From_Buffer(9 + (i*32));
				name_comp[10] = FCD_FAT160_Read_Byte_From_Buffer(10 + (i*32));

				if (FCI_COMPARE(mx_name_ext,11,name_comp,11,1) == 0)				//Perform filename comparison
				{
					mx_file_entry = i;												//Store file address
					mx_file_address = mx_current_address;
					mx_file_sector = 1;

					mx_cluster = FCD_FAT160_Read_Byte_From_Buffer(26 + (i*32));									//Read Cluster of data start
					mx_cluster = mx_cluster | ( FCD_FAT160_Read_Byte_From_Buffer(27 + (i*32)) << 8);
					#if (MX_FAT_TYPE == 1 || MX_FAT_TYPE == 2)
						if(mx_fat_system == 1)
						{
							mx_cluster = mx_cluster | ( (long) FCD_FAT160_Read_Byte_From_Buffer(20 + (i*32)) << 16);
							mx_cluster = mx_cluster | ( (long) FCD_FAT160_Read_Byte_From_Buffer(21 + (i*32)) << 24);
						}
					#endif

					mx_file_size = FCD_FAT160_Read_Byte_From_Buffer(28 + (i*32));									//Read Filesize in bytes
					mx_file_size = mx_file_size | ( FCD_FAT160_Read_Byte_From_Buffer(29 + (i*32)) << 8);
					mx_file_size = mx_file_size | ( (long) FCD_FAT160_Read_Byte_From_Buffer(30 + (i*32)) << 16);
					mx_file_size = mx_file_size | ( (long) FCD_FAT160_Read_Byte_From_Buffer(31 + (i*32)) << 24);

					if (mx_cluster == 0)																//Empty File - Assign a free mx_cluster
					{
						idx_fat = 1;
						fat_address = 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 == 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;
							}
							fat_pointer = FCD_FAT160_Read_Byte_From_Buffer(idx_fat * SECT_ADDR_LEN);			//Extract data mx_cluster address
							fat_pointer = fat_pointer | ( FCD_FAT160_Read_Byte_From_Buffer((idx_fat * SECT_ADDR_LEN) + 1) << 8);

							#if (MX_FAT_TYPE == 1 || MX_FAT_TYPE == 2)
								if(mx_fat_system == 1)
								{
									fat_pointer = fat_pointer | ((long) FCD_FAT160_Read_Byte_From_Buffer((idx_fat * SECT_ADDR_LEN) + 2) << 16);
									fat_pointer = fat_pointer | ((long) FCD_FAT160_Read_Byte_From_Buffer((idx_fat * SECT_ADDR_LEN) + 3) << 24);
								}
							#endif

						}

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

						FCD_FAT160_MX_Get_Buffer(mx_current_address);												//Read sector of root directory containing file
						fat_address = ((fat_address - mx_fat_start) * FATS_PER_SECT) + idx_fat;
						mx_cluster = fat_address;
						FCD_FAT160_Write_Byte_To_Buffer(26 + (i*32), mx_cluster);									//Write new mx_cluster value
						FCD_FAT160_Write_Byte_To_Buffer(27 + (i*32), (mx_cluster >> 8));
						#if (MX_FAT_TYPE == 1 || MX_FAT_TYPE == 2)
							if(mx_fat_system == 1)
							{
								FCD_FAT160_Write_Byte_To_Buffer(20 + (i*32), ((long) mx_cluster >> 16));
								FCD_FAT160_Write_Byte_To_Buffer(21 + (i*32), ((long) mx_cluster >> 24));
							}
						#endif
						FCD_FAT160_MX_Send_Buffer(mx_current_address);												//Write mx_cluster location to card
					}

					mx_current_address = mx_data_start + ((mx_cluster - 2) * mx_sects_per_clust);		//Move to sector containing start of file   - BR 06/10 was *32
					FCD_FAT160_MX_Get_Buffer(mx_current_address);													//Read sector
					return MX_ACK_OK;
				}
			}
			mx_current_address = mx_current_address + 1;
			scount = scount + 1;																		//Move to next sector of folder
		}
		return MX_ERR_FILENOTFOUND;																		//File not found
}

char FCD_FAT160_Read_File_Sector()
{
		return FCD_FAT160_MX_Get_Buffer(mx_current_address);		//Read sector
}

short FCD_FAT160_Read_File_Length()
{
		long temp;
		temp = mx_file_sector << 9;
		if (temp <= mx_file_size)					//If file size greater then sector limit
			return 512;								//Return Sector Full

		temp = mx_file_size % 512;
		return (temp);								//Return index of next available byte
}

char FCD_FAT160_Move_To_Next_File_Sector(char Force_Next_Sector)
{
		char 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
			//mx_file_sector = mx_file_sector + 1;		//Increment file sector
			return MX_ACK_OK;
		}
		return retval;
}

char FCD_FAT160_Append_String_To_File(char* String, char MSZ_String)
{
		char idx;

		//unsigned int fat_pointer = 0xFFFF;		//BR Unused Variable

		short length;
		char retval;
		char offset = 0;

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

		length = FCD_FAT160_Read_File_Length();				//Get next empty character position
		while (length == 512)						//While characters 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 character in string
		{
			if((length + idx) == 512)				//if string extends onto another sector
			{
				length = 0;
				offset = idx;

				FCD_FAT160_MX_Send_Buffer(mx_current_address);			//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 character from string into buffer
		}

		FCD_FAT160_MX_Send_Buffer(mx_current_address);								//Write string data in current sector to card
		mx_file_size = mx_file_size + MSZ_String;								//Update file length
		FCD_FAT160_MX_Get_Buffer(mx_file_address);									//Read file address
		FCD_FAT160_Write_Byte_To_Buffer((28 + (mx_file_entry * 32)), mx_file_size);				//Update file length in buffer
		FCD_FAT160_Write_Byte_To_Buffer((29 + (mx_file_entry * 32)), mx_file_size >> 8);
		FCD_FAT160_Write_Byte_To_Buffer((30 + (mx_file_entry * 32)), mx_file_size >> 16);
		FCD_FAT160_Write_Byte_To_Buffer((31 + (mx_file_entry * 32)), mx_file_size >> 24);
		FCD_FAT160_MX_Send_Buffer(mx_file_address);									//Update file length on card
		FCD_FAT160_MX_Send_Buffer(mx_file_address + mx_fat_size);						//Mirror data onto FAT 2
		FCD_FAT160_MX_Get_Buffer(mx_current_address);									//Read current sector
		return MX_ACK_OK;														//String appended to file
}

char FCD_FAT160_Write_File_Sector()
{
		if ((mx_file_size >> 9) == (mx_file_sector - 1))	//Is this the last sector of the file
			mx_file_size = (mx_file_size + (512 - FCD_FAT160_Read_File_Length()));

		FCD_FAT160_MX_Send_Buffer(mx_current_address);								//Write string data in current sector to card
		FCD_FAT160_MX_Get_Buffer(mx_file_address);									//Read file address
		FCD_FAT160_Write_Byte_To_Buffer((28 + (mx_file_entry * 32)), mx_file_size);				//Update file length in buffer
		FCD_FAT160_Write_Byte_To_Buffer((29 + (mx_file_entry * 32)), mx_file_size >> 8);
		FCD_FAT160_Write_Byte_To_Buffer((30 + (mx_file_entry * 32)), mx_file_size >> 16);
		FCD_FAT160_Write_Byte_To_Buffer((31 + (mx_file_entry * 32)), mx_file_size >> 24);
		FCD_FAT160_MX_Send_Buffer(mx_file_address);									//Update file length on card
		FCD_FAT160_MX_Send_Buffer(mx_file_address + mx_fat_size);						//Mirror data onto FAT 2
		FCD_FAT160_MX_Get_Buffer(mx_current_address);									//Read current sector

		return MX_ACK_OK;
}

char FCD_FAT160_Create_File(char* File_Name, char MSZ_File_Name)
{
		char i, j;

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

		FCD_FAT160_MX_Format_File_String(File_Name, MSZ_File_Name);					//Convert filename to 8.3 format
		mx_current_address = mx_folder_start;								//Move to start of root
		while (mx_current_address < (mx_folder_start + mx_folder_size))
		{
			FCD_FAT160_MX_Get_Buffer(mx_current_address);								//Read sector of root directory
			for(i=0;i<16;i++)											//16 file or directory references per sector
			{
				if (( FCD_FAT160_Read_Byte_From_Buffer(i * 32) == 0xe5) || ( FCD_FAT160_Read_Byte_From_Buffer(i * 32) == 0x00))		//Deleted or unused entry
				{
					for (j=0;j<11;j++)
					{
						FCD_FAT160_Write_Byte_To_Buffer((i * 32) + j, mx_name_ext[j]);
					}
					FCD_FAT160_Write_Byte_To_Buffer((i * 32) + 11, 0x20);						//File Attribute
					FCD_FAT160_Write_Byte_To_Buffer((i * 32) + 12, 0x18);						//Reserved for NT
					FCD_FAT160_Write_Byte_To_Buffer((i * 32) + 13, 0);							//Creation time
					FCD_FAT160_Write_Byte_To_Buffer((i * 32) + 14, MX_FILE_CREATETIME);
					FCD_FAT160_Write_Byte_To_Buffer((i * 32) + 15, MX_FILE_CREATETIME >> 8);
					FCD_FAT160_Write_Byte_To_Buffer((i * 32) + 16, MX_FILE_CREATEDATE);		//Creation date
					FCD_FAT160_Write_Byte_To_Buffer((i * 32) + 17, MX_FILE_CREATEDATE >> 8);
					FCD_FAT160_Write_Byte_To_Buffer((i * 32) + 18, MX_FILE_CREATEDATE);		//Access date
					FCD_FAT160_Write_Byte_To_Buffer((i * 32) + 19, MX_FILE_CREATEDATE >> 8);
					FCD_FAT160_Write_Byte_To_Buffer((i * 32) + 20, 0x00);
					FCD_FAT160_Write_Byte_To_Buffer((i * 32) + 21, 0x00);
					FCD_FAT160_Write_Byte_To_Buffer((i * 32) + 22, MX_FILE_CREATETIME);		//Modified time 0 no modification entry
					FCD_FAT160_Write_Byte_To_Buffer((i * 32) + 23, MX_FILE_CREATETIME >> 8);
					FCD_FAT160_Write_Byte_To_Buffer((i * 32) + 24, MX_FILE_CREATEDATE);		//Modified date
					FCD_FAT160_Write_Byte_To_Buffer((i * 32) + 25, MX_FILE_CREATEDATE >> 8);

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

char FCD_FAT160_Delete_File(char* File_Name, char MSZ_File_Name)
{
		unsigned int scount;
		char name_comp[11];
		unsigned long fat_address;
		char i;

		#if (MX_FAT_TYPE == 0)
			unsigned int temp_mx_cluster;
		#endif
		#if (MX_FAT_TYPE == 1 || MX_FAT_TYPE == 2)
			unsigned long temp_mx_cluster;
		#endif

		FCD_FAT160_MX_Format_File_String(File_Name, MSZ_File_Name);						//Convert filename to 8.3 format
		scount = 0;
		mx_current_address = mx_folder_start;									//Move to start of root
		while (scount <= mx_folder_size)
		{
			FCD_FAT160_MX_Get_Buffer(mx_current_address);									//Read sector of root directory
			for(i=0;i<16;i++)													//16 file or directory references per sector
			{
				name_comp[0] = FCD_FAT160_Read_Byte_From_Buffer(0 + (i*32));							//Move DOS 8.3 Filename into 2nd comparison buffer
				name_comp[1] = FCD_FAT160_Read_Byte_From_Buffer(1 + (i*32));
				name_comp[2] = FCD_FAT160_Read_Byte_From_Buffer(2 + (i*32));
				name_comp[3] = FCD_FAT160_Read_Byte_From_Buffer(3 + (i*32));
				name_comp[4] = FCD_FAT160_Read_Byte_From_Buffer(4 + (i*32));
				name_comp[5] = FCD_FAT160_Read_Byte_From_Buffer(5 + (i*32));
				name_comp[6] = FCD_FAT160_Read_Byte_From_Buffer(6 + (i*32));
				name_comp[7] = FCD_FAT160_Read_Byte_From_Buffer(7 + (i*32));
				name_comp[8] = FCD_FAT160_Read_Byte_From_Buffer(8 + (i*32));
				name_comp[9] = FCD_FAT160_Read_Byte_From_Buffer(9 + (i*32));
				name_comp[10] = FCD_FAT160_Read_Byte_From_Buffer(10 + (i*32));

				if (FCI_COMPARE(mx_name_ext,11,name_comp,11,1) == 0)			//Perform filename comparison
				{
					mx_cluster = FCD_FAT160_Read_Byte_From_Buffer(26 + (i*32));						//Read Cluster of data start
					mx_cluster = mx_cluster | ( FCD_FAT160_Read_Byte_From_Buffer(27 + (i*32)) << 8);
					FCD_FAT160_Write_Byte_To_Buffer(26 + (i*32), 0);								//Overwrite mx_cluster value
					FCD_FAT160_Write_Byte_To_Buffer(27 + (i*32), 0);
					#if(MX_FAT_TYPE == 1 || MX_FAT_TYPE == 2)
						if (mx_fat_system == 1)
						{
							FCD_FAT160_Write_Byte_To_Buffer(20 + (i*32), 0);
							FCD_FAT160_Write_Byte_To_Buffer(21 + (i*32), 0);
						}
					#endif

					FCD_FAT160_Write_Byte_To_Buffer(28 + (i*32), 0);								//Clear file size
					FCD_FAT160_Write_Byte_To_Buffer(29 + (i*32), 0);
					FCD_FAT160_Write_Byte_To_Buffer(30 + (i*32), 0);
					FCD_FAT160_Write_Byte_To_Buffer(31 + (i*32), 0);
					FCD_FAT160_Write_Byte_To_Buffer(0 + (i*32), 0xe5);								//Set first byte to free file flag
					FCD_FAT160_MX_Send_Buffer(mx_current_address);							//Write the free file flag to the card

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

						fat_address = mx_fat_start;								//Move to start of FAT
						while(mx_cluster >= FATS_PER_SECT)
						{
							fat_address = fat_address + 1;						//Move to next sector of FAT
							mx_cluster = mx_cluster - FATS_PER_SECT;
						}
						FCD_FAT160_MX_Get_Buffer(fat_address);								//Read FAT sector

						temp_mx_cluster = mx_cluster;
						mx_cluster = FCD_FAT160_Read_Byte_From_Buffer(temp_mx_cluster * FATS_PER_SECT);			//Read next mx_cluster value
						mx_cluster = mx_cluster | ( FCD_FAT160_Read_Byte_From_Buffer((temp_mx_cluster * FATS_PER_SECT) + 1) << 8);

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

						FCD_FAT160_MX_Send_Buffer(fat_address);
						FCD_FAT160_MX_Send_Buffer(fat_address + mx_fat_size);				//Mirror data onto FAT 2
					}
					return 0;													//File deleted correctly
				}
			}
			scount = scount + 1;
			mx_current_address = mx_current_address + 1;
		}
		return MX_ERR_FILENOTFOUND;												//File not found
}

void FCD_FAT160_Write_Byte_To_Buffer(short Address, char Data)
{
		if (Address > 255)				//BufferH
		{
			Address = Address - 256;
			mx_card_bufferh[Address] = Data;
		}
		else							//BufferL
		{
			mx_card_bufferl[Address] = Data;
		}
}

char FCD_FAT160_Read_Byte_From_Buffer(short Address)
{
		if (Address > 255)						//BufferH
		{
			Address = Address - 256;
			return (mx_card_bufferh[Address]);
		}
		else return (mx_card_bufferl[Address]);	//BufferL
}

char FCD_FAT160_Open_Folder(char* Folder_Name, char MSZ_Folder_Name)
{
	
	// ".." - Up a level
	// "root" - Root directory
	// "foldername" - Down a level

		char i;
		unsigned int scount;
		char name_comp[11];

		//Root Directory
		if (Folder_Name[0] == 'r' && Folder_Name[1] == 'o' && Folder_Name[2] == 'o' && Folder_Name[3] == 't')
		{
			mx_folder_start = mx_root_start;		//Assign root start address to folder start
			mx_folder_size = mx_root_sectors;		//Assign root size to folder size
			return (0);								//Root Directory Specified
		}

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

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

		scount = 0;
		mx_current_address = mx_folder_start;										//Move to start of folder
		while (scount < mx_folder_size)
		{
			FCD_FAT160_MX_Get_Buffer(mx_current_address);										//Read sector of root directory
			for(i=0;i<16;i++)														//16 file or directory references per sector
			{
				name_comp[0] = FCD_FAT160_Read_Byte_From_Buffer(0 + (i*32));					//Move DOS 8.3 Filename into 2nd comparison buffer
				name_comp[1] = FCD_FAT160_Read_Byte_From_Buffer(1 + (i*32));
				name_comp[2] = FCD_FAT160_Read_Byte_From_Buffer(2 + (i*32));
				name_comp[3] = FCD_FAT160_Read_Byte_From_Buffer(3 + (i*32));
				name_comp[4] = FCD_FAT160_Read_Byte_From_Buffer(4 + (i*32));
				name_comp[5] = FCD_FAT160_Read_Byte_From_Buffer(5 + (i*32));
				name_comp[6] = FCD_FAT160_Read_Byte_From_Buffer(6 + (i*32));
				name_comp[7] = FCD_FAT160_Read_Byte_From_Buffer(7 + (i*32));
				name_comp[8] = FCD_FAT160_Read_Byte_From_Buffer(8 + (i*32));
				name_comp[9] = FCD_FAT160_Read_Byte_From_Buffer(9 + (i*32));
				name_comp[10] = FCD_FAT160_Read_Byte_From_Buffer(10 + (i*32));

				if (FCI_COMPARE(mx_name_ext,11,name_comp,11,1) == 0)				//Perform filename comparison
				{
					mx_cluster = FCD_FAT160_Read_Byte_From_Buffer(26 + (i*32));							//Read Cluster of folder start
					mx_cluster = mx_cluster | ( FCD_FAT160_Read_Byte_From_Buffer(27 + (i*32)) << 8);
					#if	(MX_FAT_TYPE == 1 || MX_FAT_TYPE == 2)
						if (mx_fat_system == 1)
						{
							mx_cluster = mx_cluster | ( FCD_FAT160_Read_Byte_From_Buffer(20 + (i*32)) << 16);
							mx_cluster = mx_cluster | ( FCD_FAT160_Read_Byte_From_Buffer(21 + (i*32)) << 24);
						}
					#endif

					if (mx_cluster > 1)
					{
						mx_folder_start = mx_data_start + ((mx_cluster - 2) * mx_sects_per_clust);		//Assign folder start address - BR 06/10 was * 32
						mx_folder_size = mx_sects_per_clust;											//Assign folder size - BR 06/10 was *32											//Assign folder size
					}
					else
					{
						mx_folder_start = mx_root_start;							//Assign root start address to folder start
						mx_folder_size = mx_root_sectors;							//Assign root size to folder size
					}
					return MX_ACK_OK;												//Folder found and moved
				}
			}
			mx_current_address = mx_current_address + 1;
			scount = scount + 1;													//Move to next sector of folder
		}
		return MX_ERR_FILENOTFOUND;													//Folder not found
}

short FCD_FAT160_Scan_Current_Folder(short Current_Idx, char Scan_Type)
{
		char i;

		if (Current_Idx < (mx_folder_size * 16))
		{
			mx_current_address = mx_folder_start;							//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
				mx_current_address = mx_current_address + 1;				//Increment sector address
			}

			FCD_FAT160_MX_Get_Buffer(mx_current_address);								//Read sector of root directory

			if (( FCD_FAT160_Read_Byte_From_Buffer(Current_Idx  * 32) == 0xe5) || ( FCD_FAT160_Read_Byte_From_Buffer(Current_Idx  * 32) == 0x00) || ( FCD_FAT160_Read_Byte_From_Buffer((Current_Idx * 32) + 2) == 0x00))		//Deleted or unused entry
				return MX_ACK_FILEEMPTY;									//Address is empty

			if(Scan_Type)	//scan for folder
			{
				if (( FCD_FAT160_Read_Byte_From_Buffer((Current_Idx  * 32) + 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((Current_Idx  * 32) + 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++)
				mx_name_ext[i] = FCD_FAT160_Read_Byte_From_Buffer((Current_Idx * 32) + 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 (mx_name_ext[i] == 0x20)								//If a padding space has been found
						break;
				}
				mx_name_ext[i] = '.';										//Add the '.' seperator to the filename
				mx_name_ext[i + 1] = FCD_FAT160_Read_Byte_From_Buffer((Current_Idx * 32) + 8);
				mx_name_ext[i + 2] = FCD_FAT160_Read_Byte_From_Buffer((Current_Idx * 32) + 9);
				mx_name_ext[i + 3] = FCD_FAT160_Read_Byte_From_Buffer((Current_Idx * 32) + 10);
				for (i=i+4;i<12;i++)
					mx_name_ext[i] = ' ';
			}
			return MX_ACK_OK;												//File/folder found and stored into string array
		}
		return MX_ACK_EOF;													//End of folder reached

}

char FCD_FAT160_Read_Byte_From_Scan(char idx)
{
		if(idx > 11)
			return 0;				//String buffer 12 chars long max
		return (mx_name_ext[idx]);	//Return character from string
}

char FCD_FAT160_MX_SPI_BYTE(char shift)
{
	
		#if (MX_HW_SPI == 0)								//Software Mode

			char idx;
			for (idx = 0; idx < 8; idx++)
			{
				if (test_bit(shift, 7))
					set_bit(MX_CARD_PORT, MX_CARD_SDO);		// Set SDO bit
				else
					clear_bit(MX_CARD_PORT, MX_CARD_SDO);	// Clear SDO bit

				shift = shift << 1;

				set_bit(MX_CARD_PORT, MX_CARD_SCK);			// SCK Output 1

				delay_us(1);	//Added BR 06/10

				if(test_bit(MX_CARD_PORT, MX_CARD_SDI))
					shift = shift | 0x01;
				else
					shift = shift & 0xFE;

				clear_bit(MX_CARD_PORT, MX_CARD_SCK);		// SCK Output 0
			}
			return shift;

		#endif

		#if (MX_HW_SPI == 1)								//Hardware Mode

			#ifndef MX_SPI
				#ifdef _BOOSTC
					#pragma error "Chip does not have SPI capability"
				#endif
				#ifdef HI_TECH_C
					#error Chip does not have SPI capability
				#endif
			#endif

			sspbuf = shift;									//write the Char
			while ((sspstat & 0x01) == 0);					//wait until sspbuf is empty
			shift = sspbuf;									//receive the Char
			return shift;

		#endif

}

char FCD_FAT160_MX_Init_Card()
{
		char RetVal;
		short i;

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

		set_bit(MX_CARD_PORT, MX_CARD_CS);		//CARD-Disabled
		for(i = 0; i < 10; i++)					//Start CARD in SPI mode
		{
			FCD_FAT160_MX_SPI_BYTE(0xFF);							//Send 10*8=80 clock pulses
		}
		clear_bit(MX_CARD_PORT, MX_CARD_CS);	//CARD-Enabled
		delay_us(50);							//Wait 50us

		//Command 0 - Goto Idle State - Resets card
		FCD_FAT160_MX_SPI_BYTE(0x40);						//Send Command 0
		FCD_FAT160_MX_SPI_BYTE(0x00);						//Arg3
		FCD_FAT160_MX_SPI_BYTE(0x00);						//Arg2
		FCD_FAT160_MX_SPI_BYTE(0x00);						//Arg1
		FCD_FAT160_MX_SPI_BYTE(0x00);						//Arg0
		FCD_FAT160_MX_SPI_BYTE(0x95);						//CRC
		FCD_FAT160_MX_SPI_BYTE(0xFF);
		RetVal = FCD_FAT160_MX_SPI_BYTE(0xFF);				//Wait for response of 1
		if (RetVal != 1)
			return MX_ERR_NOCARD;				//Card not initialising or not present

		set_bit(MX_CARD_PORT, MX_CARD_CS);		//CARD-Disabled
		delay_us(50);							//Wait 50us
		clear_bit(MX_CARD_PORT, MX_CARD_CS);	//CARD-Enabled - Command 0 complete

		//Command 1 - Send Operating Condition - Reports the status of the card
		i = 512;
		while ((RetVal != 0) && (i))			//Loop while processing command 1
		{
			i = i - 1;
			set_bit(MX_CARD_PORT, MX_CARD_CS);	//CARD-Disabled
			FCD_FAT160_MX_SPI_BYTE(0xFF);
			FCD_FAT160_MX_SPI_BYTE(0xFF);
			clear_bit(MX_CARD_PORT, MX_CARD_CS);//CARD-Enabled - Command 0 complete
			FCD_FAT160_MX_SPI_BYTE(0x41);					//Send Command 1
			FCD_FAT160_MX_SPI_BYTE(0x00);					//Arg3
			FCD_FAT160_MX_SPI_BYTE(0x00);					//Arg2
			FCD_FAT160_MX_SPI_BYTE(0x00);					//Arg1
			FCD_FAT160_MX_SPI_BYTE(0x00);					//Arg0
			FCD_FAT160_MX_SPI_BYTE(0xFF);					//CRC
			FCD_FAT160_MX_SPI_BYTE(0xFF);
			RetVal = FCD_FAT160_MX_SPI_BYTE(0xFF);			//Check Response
		}
		set_bit(MX_CARD_PORT, MX_CARD_CS);		//CARD-Disabled
		if (i == 0)
			return MX_ERR_NORESP;				//Card not responding

		#if (MX_HW_SPI == 1)					//Hardware Mode only
			#ifdef _BOOSTC
				#ifdef SSPCON							// SPI Low Speed for Initialise
					sspcon = 0;
					st_bit(sspcon, SSPEN);
				#endif
				#ifdef SSPCON1
					sspcon1 = 0;
					st_bit(sspcon1, SSPEN);
				#endif
			#endif

			#ifdef HI_TECH_C
				#ifdef sspcon							// SPI Low Speed for Initialise
					sspcon = 0;
					st_bit(sspcon, SSPEN);
				#endif
				#ifdef sspcon1
					sspcon1 = 0;
					st_bit(sspcon1, SSPEN);
				#endif
			#endif
		#endif

		return MX_ACK_OK;						//Card Ready
}

char FCD_FAT160_MX_Send_Buffer(long address)
{
		int idx;
		char retval;

		address = address << 9;

		set_bit(MX_CARD_PORT, MX_CARD_CS);		//CARD-Disabled
		FCD_FAT160_MX_SPI_BYTE(0xFF); 						//Padd Command
		clear_bit(MX_CARD_PORT, MX_CARD_CS);	//CARD-Enabled
		FCD_FAT160_MX_SPI_BYTE(0x58);  					//Send command
		FCD_FAT160_MX_SPI_BYTE(((long) address >> 24) & 0xFF);	//Send MSB Of Address
		FCD_FAT160_MX_SPI_BYTE(((long) address >> 16) & 0xFF);
		FCD_FAT160_MX_SPI_BYTE((address >> 8) & 0xFF);
		FCD_FAT160_MX_SPI_BYTE(address & 0xFF);			//Send LSB Of Address
		FCD_FAT160_MX_SPI_BYTE(0xFF);  					//Skip CRC Check
		idx = 1024;
		retval = FCD_FAT160_MX_SPI_BYTE(0xFF);
		while ((retval == 0xFF) && idx)
		{
			retval = FCD_FAT160_MX_SPI_BYTE(0xFF);  		//Wait for card
			idx = idx - 1;
		}
		if (idx == 0)
		{
			set_bit(MX_CARD_PORT, MX_CARD_CS);	//CARD-Disabled
			return MX_ERR_NOACK;				//Command not acknowledged
		}

		FCD_FAT160_MX_SPI_BYTE(0xFE);						//Send Start Byte
		for (idx=0; idx < 256; idx++)			//Write Low Buffer
		{
			FCD_FAT160_MX_SPI_BYTE(mx_card_bufferl[idx]);
		}
		for (idx=0; idx < 256; idx++)			//Write High Buffer
		{
			FCD_FAT160_MX_SPI_BYTE(mx_card_bufferh[idx]);
		}
		FCD_FAT160_MX_SPI_BYTE(0xFF);								//Send 2 dummy bytes to skip CRC
		FCD_FAT160_MX_SPI_BYTE(0xFF);
		idx = 10000;
		retval = FCD_FAT160_MX_SPI_BYTE(0xFF);						//Check if CARD is still busy
		while((retval != 0xFF) && idx)
		{
			retval = FCD_FAT160_MX_SPI_BYTE(0xFF);					//Wait until CARD is not busy anymore
			idx = idx - 1;
		}
		if (idx == 0)
		{
			set_bit(MX_CARD_PORT, MX_CARD_CS);	//CARD-Disabled
			return MX_ERR_TOUT;					//Read timed out
		}
		set_bit(MX_CARD_PORT, MX_CARD_CS);		//CARD-Disabled
		return MX_ACK_OK;						//Write Complete
}

char FCD_FAT160_MX_Get_Buffer(long address)
{
		short idx;
		int CRC;
		char temp;
		unsigned int count;

		address = address << 9;

		FCD_FAT160_MX_Clear_Buffer();
		clear_bit(MX_CARD_PORT, MX_CARD_CS);		//CARD-Enabled

		FCD_FAT160_MX_SPI_BYTE(0xFF);							//Send Dummy Byte
		FCD_FAT160_MX_SPI_BYTE(0x51);							//Send Read Command
		FCD_FAT160_MX_SPI_BYTE(((long) address >> 24) & 0xFF);		//Send MSB Of Address
		FCD_FAT160_MX_SPI_BYTE(((long) address >> 16) & 0xFF);
		FCD_FAT160_MX_SPI_BYTE((address >> 8) & 0xFF);
		FCD_FAT160_MX_SPI_BYTE(address & 0xFF);				//Send LSB Of Address
		FCD_FAT160_MX_SPI_BYTE(0xFF);							//CRC unused

		temp = 0xFF;
		count = 10;
		while((temp == 0xFF) && count)
		{
			temp = FCD_FAT160_MX_SPI_BYTE(0xFF);				//Wait for response
			count = count - 1;
		}
		if (count == 0)
		{
			set_bit(MX_CARD_PORT, MX_CARD_CS);			//CARD-Disabled
			return MX_ERR_NOACK;					//Read Not Acknowledged
		}

		temp = 0;
		count = 65000;
		while ((temp != 0xFE) && count)			//Wait for data ready
		{
			temp = FCD_FAT160_MX_SPI_BYTE(0xFF);
			delay_us(10);
			count = count - 1;
		}
		if (count == 0)
			return MX_ERR_TOUT	;					//Read Timed Out

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

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

		CRC = FCD_FAT160_MX_SPI_BYTE(0xFF);					//Read 16-Bit CRC
		CRC = CRC << 8;
		CRC = CRC | FCD_FAT160_MX_SPI_BYTE(0xFF);

		set_bit(MX_CARD_PORT, MX_CARD_CS);			//CARD-Disabled
		FCD_FAT160_MX_SPI_BYTE(0xFF);							//Trailing byte
		return MX_ACK_OK;							//Read Complete
}

void FCD_FAT160_MX_Format_File_String(char* File_Name, char MSZ_File_Name)
{
		char i;
		for (i=0;i<11;i++)
			mx_name_ext[i] = 0x20;											//Fill name variable with spaces

		FCI_TOUPPER(File_Name,MSZ_File_Name,File_Name,MSZ_File_Name);	//convert to uppercase

		for (i=0; i<8 && *File_Name != '.' && *File_Name; i++)			//Copy file name to comparison variable
			mx_name_ext[i] = *File_Name++;

		if(*File_Name == '.')											//Find the '.' seperator
		{
			File_Name++;												//and then shift the extension
			for(i=8;i<11 && *File_Name; i++)
				mx_name_ext[i] = *File_Name++;
		}
}

void FCD_FAT160_MX_Add_Sector_To_File()
{
		unsigned long idx_fat;
		unsigned long fat_address;

		#if (MX_FAT_TYPE == 0)
			unsigned int fat_pointer = 0xFFFF;				//16-bit FAT pointer
		#endif
		#if (MX_FAT_TYPE == 1)
			unsigned long fat_pointer = 0x0FFFFFFF;			//32-bit FAT pointer
		#endif
		#if (MX_FAT_TYPE == 2)
			unsigned long fat_pointer;
			if (mx_fat_system == 1)
				fat_pointer = 0x0FFFFFFF;					//32-bit FAT pointer
			else
				fat_pointer = 0xFFFF;						//16-bit FAT pointer
		#endif

		idx_fat = 1;
		fat_address = 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;							//Increment FAT address - Start at address 2
			if(idx_fat == 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;
			}
			fat_pointer = FCD_FAT160_Read_Byte_From_Buffer(idx_fat * SECT_ADDR_LEN);			//Extract data mx_cluster address
			fat_pointer = fat_pointer | ( FCD_FAT160_Read_Byte_From_Buffer((idx_fat * SECT_ADDR_LEN) + 1) << 8);
			#if (MX_FAT_TYPE == 1 || MX_FAT_TYPE == 2)
				if (mx_fat_system == 1)
				{
					fat_pointer = fat_pointer | ((long) FCD_FAT160_Read_Byte_From_Buffer((idx_fat * SECT_ADDR_LEN) + 2) << 16);
					fat_pointer = fat_pointer | ((long) FCD_FAT160_Read_Byte_From_Buffer((idx_fat * SECT_ADDR_LEN) + 3) << 24);
				}
			#endif
		}

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

		#if (MX_FAT_TYPE == 1 || MX_FAT_TYPE == 2)
			if (mx_fat_system == 1)
			{
				FCD_FAT160_Write_Byte_To_Buffer(((idx_fat * SECT_ADDR_LEN) + 2), 0xFF);
				FCD_FAT160_Write_Byte_To_Buffer(((idx_fat * SECT_ADDR_LEN) + 3), 0x0F);
			}
		#endif

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

		fat_address = ((fat_address - mx_fat_start) * FATS_PER_SECT) + idx_fat;
		idx_fat = mx_cluster;
		mx_cluster = fat_address;								//Store new mx_cluster address

		fat_address = mx_fat_start;
		while (idx_fat >= FATS_PER_SECT)
		{
			idx_fat = idx_fat - FATS_PER_SECT;
			fat_address = fat_address + 1;
		}
		FCD_FAT160_MX_Get_Buffer(fat_address);
		FCD_FAT160_Write_Byte_To_Buffer((idx_fat * SECT_ADDR_LEN), mx_cluster);				//Update old FAT address
		FCD_FAT160_Write_Byte_To_Buffer(((idx_fat * SECT_ADDR_LEN) + 1), (mx_cluster >> 8));

		#if (MX_FAT_TYPE == 1 || MX_FAT_TYPE == 2)
			if (mx_fat_system == 1)
			{
				FCD_FAT160_Write_Byte_To_Buffer(((idx_fat * SECT_ADDR_LEN) + 2), (mx_cluster >> 16));
				FCD_FAT160_Write_Byte_To_Buffer(((idx_fat * SECT_ADDR_LEN) + 3), (mx_cluster >> 24));
			}
		#endif

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

		mx_file_sector = mx_file_sector + 1;						//Increment file sector
		mx_current_address = mx_data_start + ((mx_cluster - 2) * mx_sects_per_clust);//Move to next sector in file		BR 06/10 was * 32
		FCD_FAT160_MX_Get_Buffer(mx_current_address);
}

void FCD_FAT160_MX_Clear_Buffer()
{
		short count;

		for (count = 0; count < 256; count++)
		{
			mx_card_bufferh[count] = 0x00;
			mx_card_bufferl[count] = 0x00;
		}
}

char FCD_FAT160_Read_Next_File_Sector()
{
	
		#if (MX_FAT_TYPE == 0)
			unsigned int temp_mx_cluster;
			unsigned int old_mx_cluster;
		#endif
		#if (MX_FAT_TYPE == 1 || MX_FAT_TYPE == 2)
			unsigned long temp_mx_cluster;
			unsigned long old_mx_cluster;
		#endif

		unsigned long fat_address;
		char retval;

		mx_current_address = mx_current_address + 1;								//Increment address
		if (((mx_current_address - mx_data_start) % mx_sects_per_clust) == 0)		//If end of mx_cluster reached then find next mx_cluster BR 06/10 was % 32
		{
			temp_mx_cluster = mx_cluster;
			fat_address = mx_fat_start;												//Move to start of FAT
			while (temp_mx_cluster >= FATS_PER_SECT)								//256 FAT16 / 128 FAT32 entries per sector
			{
				temp_mx_cluster = temp_mx_cluster - 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 = mx_cluster;
			mx_cluster = FCD_FAT160_Read_Byte_From_Buffer(temp_mx_cluster * SECT_ADDR_LEN);	//Extract data mx_cluster address
			mx_cluster = mx_cluster | ( FCD_FAT160_Read_Byte_From_Buffer((temp_mx_cluster * SECT_ADDR_LEN) + 1) << 8);

			#if	(MX_FAT_TYPE == 1 || MX_FAT_TYPE == 2)
				if (mx_fat_system == 1)
				{
					mx_cluster = mx_cluster | ((long) FCD_FAT160_Read_Byte_From_Buffer((temp_mx_cluster * SECT_ADDR_LEN) + 2) << 16);
					mx_cluster = mx_cluster | ((long) FCD_FAT160_Read_Byte_From_Buffer((temp_mx_cluster * SECT_ADDR_LEN) + 3) << 24);
				}
			#endif

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

				mx_current_address = mx_current_address - 1;						//Restore address
				mx_cluster = old_mx_cluster;										//Restore mx_cluster
				FCD_FAT160_MX_Get_Buffer(mx_current_address);									//Read sector
				return retval;
			}

			mx_current_address = mx_data_start + ((mx_cluster - 2) * mx_sects_per_clust);			//Move to next sector in file   BR 06/10 was * 32
		}

		mx_file_sector = mx_file_sector + 1;										//Increment file sector

		return FCD_FAT160_MX_Get_Buffer(mx_current_address);									//Read sector
}

//Macro implementations

void main()
{
	
	//Initialisation
	adcon1 = 0x0F;
	ucfg = 0x08;
cr_bit(pie2, USBIE);

	
	#if (MX_HW_SPI == 0)							//Software Mode

		//Configure Port Pin Data Direction
	    clear_bit(MX_CARD_TRIS, MX_CARD_CS);		// CS Enable
	    clear_bit(MX_CARD_TRIS, MX_CARD_SCK);		// SCK Output
	    set_bit  (MX_CARD_TRIS, MX_CARD_SDI);		// SDI Input
	    clear_bit(MX_CARD_TRIS, MX_CARD_SDO);		// SDO Output

		//Configure Port Pin Default Output
		set_bit(MX_CARD_PORT, MX_CARD_SCK);			// Initialise Clock
		set_bit(MX_CARD_PORT, MX_CARD_SDO);			// Initialise Output
		set_bit(MX_CARD_PORT, MX_CARD_SDI);			// Initialise Input
		set_bit(MX_CARD_PORT, MX_CARD_CS);			// Card Disable

	#endif

	#if (MX_HW_SPI == 1)							//Hardware Mode

		#ifndef MX_SPI
			#ifdef _BOOSTC
				#pragma error "Chip does not have SPI capability"
			#endif
			#ifdef HI_TECH_C
				#error Chip does not have SPI capability
			#endif
		#endif

		#ifdef MX_SPI_B
		    set_bit(trisb,MX_SPI_SDI);				// SDI Input
		    clear_bit(trisb,MX_SPI_SDO);			// SDO Output
		    clear_bit(trisb,MX_SPI_SCK);			// SCK Output
			clear_bit(MX_CARD_TRIS, MX_CARD_CS);	// CS Enable
		    set_bit(MX_CARD_PORT, MX_CARD_CS);		// Card Disable
		#endif

		#ifdef MX_SPI_C
		    set_bit(trisc,MX_SPI_SDI);				// SDI Input
		    clear_bit(trisc,MX_SPI_SDO);			// SDO Output
		    clear_bit(trisc,MX_SPI_SCK);			// SCK Output
		    clear_bit(MX_CARD_TRIS, MX_CARD_CS);	// CS Enable
			set_bit(MX_CARD_PORT, MX_CARD_CS);		// Card Disable
		#endif

		#ifdef MX_SPI_BCB
		    set_bit(trisb,MX_SPI_SDI);				// SDI Input
			clear_bit(trisc,MX_SPI_SDO);			// SDO Output
			clear_bit(trisb,MX_SPI_SCK);			// SCK Output
			clear_bit(MX_CARD_TRIS, MX_CARD_CS);	// CS Enable
			set_bit(MX_CARD_PORT, MX_CARD_CS);		// Card Disable
		#endif

		sspstat = 64;								// Configure SPI Peripheral

		#ifdef _BOOSTC
			#ifdef SSPCON							// SPI Low Speed for Initialise
				sspcon = 2;
				st_bit(sspcon, SSPEN);
			#endif
			#ifdef SSPCON1
				sspcon1 = 2;
				st_bit(sspcon1, SSPEN);
			#endif
		#endif

		#ifdef HI_TECH_C
			#ifdef sspcon							// SPI Low Speed for Initialise
				sspcon = 2;
				st_bit(sspcon, SSPEN);
			#endif
			#ifdef sspcon1
				sspcon1 = 2;
				st_bit(sspcon1, SSPEN);
			#endif
		#endif

	#endif


	//Interrupt initialisation code
	


	//Start LCd
	//Call Component Macro: LCDDisplay(0)::Start
	FCD_LCDDisplay0_Start();


	//Print Startup String
	//Call Component Macro: LCDDisplay(0)::PrintString("Waiting for Card")
	FCD_LCDDisplay0_PrintString("Waiting for Card",16);


	//Call Component Macro
	//Call Component Macro: LCDDisplay(0)::Cursor(0, 1)
	FCD_LCDDisplay0_Cursor(0, 1);


	//Assign filename and data
	//String Manipulation:
	//  filename = "log1.txt"
	//  filestring = ""
	FCI_CONCATENATE("log1.txt",8,"",0,FCV_FILENAME,FCSZ_FILENAME);
	FCI_CONCATENATE("",0,"",0,FCV_FILESTRING,FCSZ_FILESTRING);
	

	//Initialise Return Value
	//Calculation:
	//  retval = 1
	//  count = 8
	//  char = 35
	FCV_RETVAL = 1;
	FCV_COUNT = 8;
	FCV_CHAR = 35;
	

	//Wait for card to start up
	//Loop: While retval > 0
	while (FCV_RETVAL > 0)
	{
		//Delay
		//Delay: 1 s
		delay_s(1);


		//Init FAT16
		//Call Component Macro: retval=FAT16(0)::Init_FAT
		FCV_RETVAL = FCD_FAT160_Init_FAT();


		//Calculation
		//Calculation:
		//  count = count-1
		FCV_COUNT = FCV_COUNT-1;
		

		//Decision
		//Decision: count=0?
		if (FCV_COUNT==0)
		{
			//Calculation
			//Calculation:
			//  count = 8
			//  char = char XOR 3
			FCV_COUNT = 8;
			FCV_CHAR = FCV_CHAR ^ 3;
			

			//Call Component Macro
			//Call Component Macro: LCDDisplay(0)::Cursor(0, 1)
			FCD_LCDDisplay0_Cursor(0, 1);


		}


		//Call Component Macro
		//Call Component Macro: LCDDisplay(0)::PrintNumber(count)
		FCD_LCDDisplay0_PrintNumber(FCV_COUNT);


		//Call Component Macro
		//Call Component Macro: LCDDisplay(0)::PrintASCII(" ")
		FCD_LCDDisplay0_PrintASCII(' ');


		//Call Component Macro
		//Call Component Macro: LCDDisplay(0)::PrintNumber(retval)
		FCD_LCDDisplay0_PrintNumber(FCV_RETVAL);


	}


	//Clear Display
	//Call Component Macro: LCDDisplay(0)::Clear
	FCD_LCDDisplay0_Clear();


	//Print Creating File
	//Call Component Macro: LCDDisplay(0)::PrintString("Creating File")
	FCD_LCDDisplay0_PrintString("Creating File",13);


	//Move to next line of LCD
	//Call Component Macro: LCDDisplay(0)::Cursor(0, 1)
	FCD_LCDDisplay0_Cursor(0, 1);


	//Create File
	//Call Component Macro: retval=FAT16(0)::Create_File(filename)
	FCV_RETVAL = FCD_FAT160_Create_File(FCV_FILENAME,FCSZ_FILENAME);


	//Decision
	//Decision: retval?
	if (FCV_RETVAL)
	{
		//File Error
		//Call Component Macro: LCDDisplay(0)::PrintString("File Exists")
		FCD_LCDDisplay0_PrintString("File Exists",11);


	} else {
		//File OK
		//Call Component Macro: LCDDisplay(0)::PrintString("File Created")
		FCD_LCDDisplay0_PrintString("File Created",12);


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


		//Clear Display
		//Call Component Macro: LCDDisplay(0)::Clear
		FCD_LCDDisplay0_Clear();


		//Print Opening File
		//Call Component Macro: LCDDisplay(0)::PrintString("Opening File")
		FCD_LCDDisplay0_PrintString("Opening File",12);


		//Move to next line of LCD
		//Call Component Macro: LCDDisplay(0)::Cursor(0, 1)
		FCD_LCDDisplay0_Cursor(0, 1);


		//Open the file
		//Call Component Macro: retval=FAT16(0)::Open_File(filename)
		FCV_RETVAL = FCD_FAT160_Open_File(FCV_FILENAME,FCSZ_FILENAME);


		//Decision
		//Decision: retval?
		if (FCV_RETVAL)
		{
			//File Error
			//Call Component Macro: LCDDisplay(0)::PrintString("File Error")
			FCD_LCDDisplay0_PrintString("File Error",10);


		} else {
			//File OK
			//Call Component Macro: LCDDisplay(0)::PrintString("File Opened")
			FCD_LCDDisplay0_PrintString("File Opened",11);


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


			//Clear Display
			//Call Component Macro: LCDDisplay(0)::Clear
			FCD_LCDDisplay0_Clear();


			//Print Writing Data
			//Call Component Macro: LCDDisplay(0)::PrintString("Writing Data")
			FCD_LCDDisplay0_PrintString("Writing Data",12);


			//Move to next line of LCD
			//Call Component Macro: LCDDisplay(0)::Cursor(0, 1)
			FCD_LCDDisplay0_Cursor(0, 1);


			//Take 20 samples
			//Loop: Loop 20 times
			for (FCLV_LOOP1=0; FCLV_LOOP1<20; FCLV_LOOP1++)
			{
				//Read into Int Variable
				//Call Component Macro: ADC_Val=ADC(0)::ReadAsInt
				FCV_ADC_VAL = FCD_ADC0_ReadAsInt();


				//Convert variable to string
				//String Manipulation:
				//  filestring = ToString$(ADC_Val)
				//  filestring = filestring + ", "
				FCI_TOSTRING(FCV_ADC_VAL,FCV_FILESTRING,FCSZ_FILESTRING);
				FCI_CONCATENATE(FCV_FILESTRING,FCSZ_FILESTRING,", ",2,FCV_FILESTRING,FCSZ_FILESTRING);
				

				//Append data to file
				//Call Component Macro: retval=FAT16(0)::Append_String_To_File(filestring)
				FCV_RETVAL = FCD_FAT160_Append_String_To_File(FCV_FILESTRING,FCSZ_FILESTRING);


			}


			//Decision
			//Decision: retval?
			if (FCV_RETVAL)
			{
				//Write Error
				//Call Component Macro: LCDDisplay(0)::PrintString("Data Error")
				FCD_LCDDisplay0_PrintString("Data Error",10);


			} else {
				//Write OK
				//Call Component Macro: LCDDisplay(0)::PrintString("Data Written")
				FCD_LCDDisplay0_PrintString("Data Written",12);


			}


		}


	}


	mainendloop: goto mainendloop;
}

void MX_INTERRUPT_MACRO(void)
{
}



