//************************************************************************************
//**  
//**  File name:     C:\Users\Ben\Desktop\Test Files\Sound Wav Player FAT16 V0.4.c
//**  Generated by:  Flowcode v4.5.18.74
//**  Date:          Thursday, September 13, 2012 11:08:02
//**  Licence:       Professional
//**  Registered to: Ben Rowland
//**  
//**  
//**  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
%C__CONFIG(%A, %V);
#endif
#ifdef _BOOSTC
#pragma DATA 0x300001, 0x4e
#endif
#ifdef _HI_TECH_C
%C__CONFIG(%A, %V);
#endif
#ifdef _BOOSTC
#pragma DATA 0x300002, 0x19
#endif
#ifdef _HI_TECH_C
%C__CONFIG(%A, %V);
#endif
#ifdef _BOOSTC
#pragma DATA 0x300003, 0x1e
#endif
#ifdef _HI_TECH_C
%C__CONFIG(%A, %V);
#endif
#ifdef _BOOSTC
#pragma DATA 0x300004, 0xff
#endif
#ifdef _HI_TECH_C
%C__CONFIG(%A, %V);
#endif
#ifdef _BOOSTC
#pragma DATA 0x300005, 0x81
#endif
#ifdef _HI_TECH_C
%C__CONFIG(%A, %V);
#endif
#ifdef _BOOSTC
#pragma DATA 0x300006, 0x80
#endif
#ifdef _HI_TECH_C
%C__CONFIG(%A, %V);
#endif
#ifdef _BOOSTC
#pragma DATA 0x300007, 0xff
#endif
#ifdef _HI_TECH_C
%C__CONFIG(%A, %V);
#endif
#ifdef _BOOSTC
#pragma DATA 0x300008, 0xf
#endif
#ifdef _HI_TECH_C
%C__CONFIG(%A, %V);
#endif
#ifdef _BOOSTC
#pragma DATA 0x300009, 0xc0
#endif
#ifdef _HI_TECH_C
%C__CONFIG(%A, %V);
#endif
#ifdef _BOOSTC
#pragma DATA 0x30000a, 0xf
#endif
#ifdef _HI_TECH_C
%C__CONFIG(%A, %V);
#endif
#ifdef _BOOSTC
#pragma DATA 0x30000b, 0xe0
#endif
#ifdef _HI_TECH_C
%C__CONFIG(%A, %V);
#endif
#ifdef _BOOSTC
#pragma DATA 0x30000c, 0xf
#endif
#ifdef _HI_TECH_C
%C__CONFIG(%A, %V);
#endif
#ifdef _BOOSTC
#pragma DATA 0x30000d, 0x40
#endif
#ifdef _HI_TECH_C
%C__CONFIG(%A, %V);
#endif

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

//Macro function declarations
void FCM_Stream_Audio_TMR0_INT();
void FCM_Fill_Backup_Buffer();


//Variable declarations
#define FCSZ_FILENAME 20
char FCV_RETVAL;
short FCV_TEMP;
char FCV_I;
char FCV_FILENAME[FCSZ_FILENAME];
char FCV_SAMPLE_FLAG;
short FCV_BYTES_IN_SECT;
short FCV_IDX;
short FCV_TEMP_ADDRESS;
char FCV_IDX_BUF;
char FCV_SAMPLE;
char FCV_NEXT_FLAG;
char FCV_BUFF_SAMPLE;
char FCV_BUFFER[112];

char FCLV_LOOP1;



//LCDDisplay(0): //Defines:

/**** Macro Substitutions ****
portd = D1 Port
trisd = D1 Data Direction
portd = D2 Port
trisd = D2 Data Direction
portd = D3 Port
trisd = D3 Data Direction
portd = D4 Port
trisd = D4 Data Direction
portd = RS Port
trisd = RS Data Direction
portd = E Port
trisd = 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_198634 = Unique Component Reference Number
2 = Row Count
16 = Column Count
******************************/

	//component connections
	#define LCD_198634_PORT0    portd
	#define LCD_198634_TRIS0    trisd
	#define LCD_198634_PORT1    portd
	#define LCD_198634_TRIS1    trisd
	#define LCD_198634_PORT2    portd
	#define LCD_198634_TRIS2    trisd
	#define LCD_198634_PORT3    portd
	#define LCD_198634_TRIS3    trisd
	#define LCD_198634_PORT4    portd
	#define LCD_198634_TRIS4    trisd
	#define LCD_198634_PORT5    portd
	#define LCD_198634_TRIS5    trisd
	#define LCD_198634_BIT0    	0
	#define LCD_198634_BIT1    	1
	#define LCD_198634_BIT2    	2
	#define LCD_198634_BIT3    	3
	#define LCD_198634_RS      	4
	#define LCD_198634_E       	5
	#define LCD_198634_ROWCNT	2
	#define LCD_198634_COLCNT	16

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

	#define ModIDLCD_198634LCD_198634 (((trisd << 5) + portd) << 9)




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


//FAT16(0): //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
16685 = File Creation Time
22785 = 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		16685
	#define MX_FILE_CREATETIME		22785
	#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 long mx_root_sectors = 0;		//Number of sectors in the root directory
	unsigned long 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();


//PWM(0): //Defines:

/**** Macro Substitutions ****
255 = Timer 2 Rollover Value
0x04 = Timer 2 Prescaler Value
-1 = MIAC System ID
0 = Alternate Pin FCD_PWM0_Enable
******************************/




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

void FCD_PWM0_Enable(char nIdx);
void FCD_PWM0_Disable(char nIdx);
void FCD_PWM0_SetDutyCycle(char nIdx, char nDuty);
void FCD_PWM0_ChangePeriod(char nPeriodVal, char nPrescalerVal);
void FCD_PWM0_SetDutyCycle10bit(char nIdx, short nDuty);



//LCDDisplay(0): //Macro implementations


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

		clear_bit(LCD_198634_PORT0, LCD_198634_BIT0);
		clear_bit(LCD_198634_PORT1, LCD_198634_BIT1);
		clear_bit(LCD_198634_PORT2, LCD_198634_BIT2);
		clear_bit(LCD_198634_PORT3, LCD_198634_BIT3);
		clear_bit(LCD_198634_PORT4, LCD_198634_RS);
		clear_bit(LCD_198634_PORT5, LCD_198634_E);
		pt = ((in >> 4) & 0x0f);
		if (pt & 0x01)
		    set_bit(LCD_198634_PORT0, LCD_198634_BIT0);
		if (pt & 0x02)
		    set_bit(LCD_198634_PORT1, LCD_198634_BIT1);
		if (pt & 0x04)
		    set_bit(LCD_198634_PORT2, LCD_198634_BIT2);
		if (pt & 0x08)
		    set_bit(LCD_198634_PORT3, LCD_198634_BIT3);
		if (mask)
		    set_bit(LCD_198634_PORT4, LCD_198634_RS);
		LCD_198634_DELAY;
		set_bit (LCD_198634_PORT5, LCD_198634_E);
		LCD_198634_DELAY;
		clear_bit (LCD_198634_PORT5, LCD_198634_E);
		pt = (in & 0x0f);
		LCD_198634_DELAY;
		clear_bit(LCD_198634_PORT0, LCD_198634_BIT0);
		clear_bit(LCD_198634_PORT1, LCD_198634_BIT1);
		clear_bit(LCD_198634_PORT2, LCD_198634_BIT2);
		clear_bit(LCD_198634_PORT3, LCD_198634_BIT3);
		clear_bit(LCD_198634_PORT4, LCD_198634_RS);
		clear_bit(LCD_198634_PORT5, LCD_198634_E);
		if (pt & 0x01)
		    set_bit(LCD_198634_PORT0, LCD_198634_BIT0);
		if (pt & 0x02)
		    set_bit(LCD_198634_PORT1, LCD_198634_BIT1);
		if (pt & 0x04)
		    set_bit(LCD_198634_PORT2, LCD_198634_BIT2);
		if (pt & 0x08)
		    set_bit(LCD_198634_PORT3, LCD_198634_BIT3);
		if (mask)
		    set_bit(LCD_198634_PORT4, LCD_198634_RS);
		LCD_198634_DELAY;
		set_bit (LCD_198634_PORT5, LCD_198634_E);
		LCD_198634_DELAY;
		clear_bit (LCD_198634_PORT5, LCD_198634_E);
		LCD_198634_DELAY;

	#endif

}

void FCD_LCDDisplay0_Start()
{
	
	#ifdef MX_MIAC_SYSTEM
	  #if (portd != MX_MIAC_MM_MIAC_BASE)

		MIAC_CAN_TX[0] = 0;
		MIAC_CAN_TX[1] = 1;
		MIAC_CAN_TX[2] = 2;
		MIAC_CAN_TX[3] = 3;
		MIAC_CAN_TX[4] = 4;
		MIAC_CAN_TX[5] = 5;

		MIAC_Module_WR(ModIDLCD_198634, 608, 6,1,1);
		MIAC_Module_GetAck(ModIDLCD_198634 + 32, 608, 20);

		MIAC_CAN_TX[0] = 2;
		MIAC_CAN_TX[1] = 16;
		MIAC_Module_WR(ModIDLCD_198634, 608, 2,0,0);
		MIAC_Module_GetAck(ModIDLCD_198634 + 32, 608, 255);

	  #endif
	#else

		clear_bit(LCD_198634_TRIS0, LCD_198634_BIT0);
		clear_bit(LCD_198634_TRIS1, LCD_198634_BIT1);
		clear_bit(LCD_198634_TRIS2, LCD_198634_BIT2);
		clear_bit(LCD_198634_TRIS3, LCD_198634_BIT3);
		clear_bit(LCD_198634_TRIS4, LCD_198634_RS);
		clear_bit(LCD_198634_TRIS5, LCD_198634_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);
	#endif

}

void FCD_LCDDisplay0_Clear()
{
	
	#ifdef MX_MIAC_SYSTEM
	  #if (portd != MX_MIAC_MM_MIAC_BASE)

		MIAC_Module_WR(ModIDLCD_198634, 609, 0,1,0);
		MIAC_Module_GetAck(ModIDLCD_198634 + 32, 609, 200);
	  #endif
	#else
		FCD_LCDDisplay0_RawSend(0x01, 0);
		Wdt_Delay_Ms(2);
		FCD_LCDDisplay0_RawSend(0x02, 0);
		Wdt_Delay_Ms(2);
	#endif

}

void FCD_LCDDisplay0_PrintASCII(char Character)
{
	
	#ifdef MX_MIAC_SYSTEM
	  #if (portd != MX_MIAC_MM_MIAC_BASE)



		MIAC_CAN_TX[0] = Character;

		MIAC_Module_WR(ModIDLCD_198634, 610, 1,1,0);
		MIAC_Module_GetAck(ModIDLCD_198634 + 32, 610, 20);
	  #endif
	#else
		FCD_LCDDisplay0_RawSend(Character, 0x10);
	#endif

}

void FCD_LCDDisplay0_Command(char in)
{
	
	#ifdef MX_MIAC_SYSTEM
	  #if (portd != MX_MIAC_MM_MIAC_BASE)

		MIAC_CAN_TX[0] = in;

		MIAC_Module_WR(ModIDLCD_198634, 611, 1,1,0);
		MIAC_Module_GetAck(ModIDLCD_198634 + 32, 611, 200);
	  #endif
	#else
		FCD_LCDDisplay0_RawSend(in, 0);
		Wdt_Delay_Ms(2);
	#endif

}

void FCD_LCDDisplay0_Cursor(char x, char y)
{
	
	#ifdef MX_MIAC_SYSTEM
	  #if (portd != MX_MIAC_MM_MIAC_BASE)

		MIAC_CAN_TX[0] = x;
		MIAC_CAN_TX[1] = y;

		MIAC_Module_WR(ModIDLCD_198634, 612, 2,1,0);
		MIAC_Module_GetAck(ModIDLCD_198634 + 32, 612, 20);
	  #endif

	#else

	  #if (LCD_198634_ROWCNT == 1)
	    y=0x80;
	  #endif

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

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

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

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

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

}

void FCD_LCDDisplay0_PrintNumber(short Number)
{
	
	#ifdef MX_MIAC_SYSTEM
	  #if (portd != MX_MIAC_MM_MIAC_BASE)

		MIAC_CAN_TX[1] = Number;
		MIAC_CAN_TX[0] = Number >> 8;

		MIAC_Module_WR(ModIDLCD_198634, 613, 4,1,0);
		MIAC_Module_GetAck(ModIDLCD_198634 + 32, 613, 200);
	  #endif

	#else

		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);
	#endif

}

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

	#ifdef MX_MIAC_SYSTEM
	  #if (portd != MX_MIAC_MM_MIAC_BASE)

		char msg_count, ch;
		char cmd_start = 1;
		char more_data = 1;

		// Split string into 6-byte packets
		do
		{
			msg_count = 0;
			do
			{
				ch = String[idx];
				if (ch)
				{
					MIAC_CAN_TX[msg_count] = ch;
					idx = idx + 1;
					msg_count = msg_count + 1;
				}
			}
			while (ch && (msg_count < 6) && (idx < MSZ_String));			// check for 2 x End Of String conditions and packet full

			if (idx == MSZ_String)											// end of string
			{
				more_data = 0;
			}else{
				if (String[idx] == 0) more_data = 0;						// next ch = null
			}

			MIAC_Module_WR(ModIDLCD_198634, 614, msg_count,cmd_start,more_data);		// TX data
			MIAC_Module_GetAck(ModIDLCD_198634 + 32, 614, 200);

			cmd_start = 0;
		}
		while (more_data);
	  #endif
	#else
		for (idx=0; idx<MSZ_String; idx++)
		{
			if (String[idx] == 0)
			{
				break;
			}
			FCD_LCDDisplay0_RawSend(String[idx], 0x10);
		}
	#endif

}

void FCD_LCDDisplay0_ScrollDisplay(char Direction, char Num_Positions)
{
	
	#ifdef MX_MIAC_SYSTEM
	  #if (portd != MX_MIAC_MM_MIAC_BASE)

		MIAC_CAN_TX[0] = Direction;
		MIAC_CAN_TX[1] = Num_Positions;

		MIAC_Module_WR(ModIDLCD_198634, 615, 2,1,0);
		MIAC_Module_GetAck(ModIDLCD_198634 + 32, 615, 20);
	  #endif
	#else

		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);
		}
	#endif

}

void FCD_LCDDisplay0_ClearLine(char Line)
{
	
	#ifdef MX_MIAC_SYSTEM
	  #if (portd != MX_MIAC_MM_MIAC_BASE)

		MIAC_CAN_TX[0] = Line;

		MIAC_Module_WR(ModIDLCD_198634, 616, 1,1,0);
		MIAC_Module_GetAck(ModIDLCD_198634 + 32, 616, 200);
	  #endif
	#else
		char count;
		char rowcount;

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

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

		#if (LCD_198634_ROWCNT == 4)
			#if (LCD_198634_COLCNT == 16)
				rowcount=16;
			#endif
			#if (LCD_198634_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);
	#endif

}

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

	#ifdef MX_MIAC_SYSTEM
	  #if (portd != MX_MIAC_MM_MIAC_BASE)

		MIAC_CAN_TX[0] = nIdx;
		MIAC_CAN_TX[1] = d0;
		MIAC_CAN_TX[2] = d1;
		MIAC_CAN_TX[3] = d2;
		MIAC_CAN_TX[4] = d3;
		MIAC_CAN_TX[5] = d4;

		MIAC_Module_WR(ModIDLCD_198634, 617, 6,1,1);
		MIAC_Module_GetAck(ModIDLCD_198634 + 32, 617, 20);

		MIAC_CAN_TX[0] = d5;
		MIAC_CAN_TX[1] = d6;
		MIAC_CAN_TX[2] = d7;

		MIAC_Module_WR(ModIDLCD_198634, 617, 3,0,0);
		MIAC_Module_GetAck(ModIDLCD_198634 + 32, 617, 200);

	  #endif
	#else

	   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);
	#endif

}



//FAT16(0): //Macro implementations


char FCD_FAT160_Init_FAT()
{
	
	#ifdef MX_MIAC_SYSTEM

		unsigned int ModID = ((trisa << 5) + porta) << 9;

		MIAC_Module_WR(ModID, 736, 0,1,0);
		MIAC_Module_GetAck(ModID + 32, 736, 255);

		return(MIAC_CAN_RX[0]);

	#else

		char retval;
		char i, num_fats, sects_per_clust;
		char iterations = 0;
		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

		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);

		while (bytes_per_sect != 512 && iterations < 20) //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);

			iterations = iterations + 1;
		}
		if (iterations == 20)														//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(0x27);									//Size of root directory x 32 byte file/directory entries
				root_size = (root_size << 8) | FCD_FAT160_Read_Byte_From_Buffer(0x26);
				root_size = (root_size << 8) | FCD_FAT160_Read_Byte_From_Buffer(0x25);
				root_size = (root_size << 8) | FCD_FAT160_Read_Byte_From_Buffer(0x24);
			}
			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(0x27);									//FAT size in sectors
			mx_fat_size = (mx_fat_size << 8) | FCD_FAT160_Read_Byte_From_Buffer(0x26);
			mx_fat_size = (mx_fat_size << 8) | FCD_FAT160_Read_Byte_From_Buffer(0x25);
			mx_fat_size = (mx_fat_size << 8) | FCD_FAT160_Read_Byte_From_Buffer(0x24);

			root_size = FCD_FAT160_Read_Byte_From_Buffer(0x2F);									//Size of root directory x 32 byte file/directory entries
			root_size = (root_size << 8) | FCD_FAT160_Read_Byte_From_Buffer(0x2E);
			root_size = (root_size << 8) | FCD_FAT160_Read_Byte_From_Buffer(0x2D);
			root_size = (root_size << 8) | FCD_FAT160_Read_Byte_From_Buffer(0x2C);

			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(0x27);									//Size of root directory x 32 byte file/directory entries
					root_size = (root_size << 8) | FCD_FAT160_Read_Byte_From_Buffer(0x26);
					root_size = (root_size << 8) | FCD_FAT160_Read_Byte_From_Buffer(0x25);
					root_size = (root_size << 8) | FCD_FAT160_Read_Byte_From_Buffer(0x24);
				}
				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(0x27);									//FAT size in sectors
				mx_fat_size = (mx_fat_size << 8) | FCD_FAT160_Read_Byte_From_Buffer(0x26);
				mx_fat_size = (mx_fat_size << 8) | FCD_FAT160_Read_Byte_From_Buffer(0x25);
				mx_fat_size = (mx_fat_size << 8) | FCD_FAT160_Read_Byte_From_Buffer(0x24);

				root_size = FCD_FAT160_Read_Byte_From_Buffer(0x2F);									//Size of root directory x 32 byte file/directory entries
				root_size = (root_size << 8) | FCD_FAT160_Read_Byte_From_Buffer(0x2E);
				root_size = (root_size << 8) | FCD_FAT160_Read_Byte_From_Buffer(0x2D);
				root_size = (root_size << 8) | FCD_FAT160_Read_Byte_From_Buffer(0x2C);

				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;

	#endif

}

char FCD_FAT160_Open_File(char* File_Name, char MSZ_File_Name)
{
	
	#ifdef MX_MIAC_SYSTEM

		unsigned int ModID = ((trisa << 5) + porta) << 9;

		char idx;
		char msg_count, ch;
		char cmd_start = 1;
		char more_data = 1;

		idx = 0;

		// Split string into 6-byte packets
		do
		{
			msg_count = 0;
			do
			{
				ch = File_Name[idx];
				if (ch)
				{
					MIAC_CAN_TX[msg_count] = ch;
					idx = idx + 1;
					msg_count = msg_count + 1;
				}
			}
			while (ch && (msg_count < 6) && (idx < MSZ_File_Name));			// check for 2 x End Of String conditions and packet full

			if (idx == MSZ_File_Name)											// end of string
			{
				more_data = 0;
			}else{
				if (File_Name[idx] == 0) more_data = 0;						// next ch = null
			}

			MIAC_Module_WR(ModID, 737, msg_count,cmd_start,more_data);		// TX data
			MIAC_Module_GetAck(ModID + 32, 737, 255);						// Check for ACK

			cmd_start = 0;
		}
		while (more_data);

		return(MIAC_CAN_RX[0]);

	#else

		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;

					#if (MX_FAT_TYPE == 1 || MX_FAT_TYPE == 2)
						if(mx_fat_system == 1)
						{
							mx_cluster = FCD_FAT160_Read_Byte_From_Buffer(21 + (i*32));									//Size of root directory x 32 byte file/directory entries
							mx_cluster = (mx_cluster << 8) | FCD_FAT160_Read_Byte_From_Buffer(20 + (i*32));
						}
					#endif
					mx_cluster = (mx_cluster << 8) | FCD_FAT160_Read_Byte_From_Buffer(27 + (i*32));
					mx_cluster = (mx_cluster << 8) | FCD_FAT160_Read_Byte_From_Buffer(26 + (i*32));

					mx_file_size = FCD_FAT160_Read_Byte_From_Buffer(31 + (mx_file_entry*32));
					mx_file_size = (mx_file_size << 8) | FCD_FAT160_Read_Byte_From_Buffer(30 + (mx_file_entry*32));
					mx_file_size = (mx_file_size << 8) | FCD_FAT160_Read_Byte_From_Buffer(29 + (mx_file_entry*32));
					mx_file_size = (mx_file_size << 8) | FCD_FAT160_Read_Byte_From_Buffer(28 + (mx_file_entry*32));

					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;
							}

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

						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

	#endif

}

char FCD_FAT160_Read_File_Sector()
{
	
	#ifdef MX_MIAC_SYSTEM

		unsigned int ModID = ((trisa << 5) + porta) << 9;

		MIAC_Module_WR(ModID, 739, 0,1,0);
		MIAC_Module_GetAck(ModID + 32, 739, 255);

		return(MIAC_CAN_RX[0]);

	#else

		return FCD_FAT160_MX_Get_Buffer(mx_current_address);		//Read sector

	#endif

}

short FCD_FAT160_Read_File_Length()
{
	
	#ifdef MX_MIAC_SYSTEM

		unsigned int ModID = ((trisa << 5) + porta) << 9;

		MIAC_Module_WR(ModID, 738, 0,1,0);
		MIAC_Module_GetAck(ModID + 32, 738, 255);

		return((MIAC_CAN_RX[0] << 8) + MIAC_CAN_RX[1]);

	#else

		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

	#endif

}

char FCD_FAT160_Move_To_Next_File_Sector(char Force_Next_Sector)
{
	
	#ifdef MX_MIAC_SYSTEM

		unsigned int ModID = ((trisa << 5) + porta) << 9;

		MIAC_CAN_TX[0] = Force_Next_Sector;

		MIAC_Module_WR(ModID, 740, 1,1,0);
		MIAC_Module_GetAck(ModID + 32, 740, 255);

		return(MIAC_CAN_RX[0]);

	#else

		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;

	#endif

}

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

	#ifdef MX_MIAC_SYSTEM

		unsigned int ModID = ((trisa << 5) + porta) << 9;

		char msg_count, ch;
		char cmd_start = 1;
		char more_data = 1;

		idx = 0;

		// Split string into 6-byte packets
		do
		{
			msg_count = 0;
			do
			{
				ch = String[idx];
				if (ch)
				{
					MIAC_CAN_TX[msg_count] = ch;
					idx = idx + 1;
					msg_count = msg_count + 1;
				}
			}
			while (ch && (msg_count < 6) && (idx < MSZ_String));			// check for 2 x End Of String conditions and packet full

			if (idx == MSZ_String)											// end of string
			{
				more_data = 0;
			}else{
				if (String[idx] == 0) more_data = 0;						// next ch = null
			}

			MIAC_Module_WR(ModID, 741, msg_count,cmd_start,more_data);		// TX data
			MIAC_Module_GetAck(ModID + 32, 741, 255);						// Check for ACK

			cmd_start = 0;
		}
		while (more_data);

		return(MIAC_CAN_RX[0]);

	#else

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

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

}

char FCD_FAT160_Write_File_Sector()
{
	
	#ifdef MX_MIAC_SYSTEM

		unsigned int ModID = ((trisa << 5) + porta) << 9;

		MIAC_Module_WR(ModID, 742, 0,1,0);
		MIAC_Module_GetAck(ModID + 32, 742, 255);

		return(MIAC_CAN_RX[0]);

	#else

		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)), ((long) mx_file_size >> 16));
		FCD_FAT160_Write_Byte_To_Buffer((31 + (mx_file_entry * 32)), ((long) mx_file_size >> 24));
		FCD_FAT160_MX_Send_Buffer(mx_file_address);									//Update file length on card
		//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;

	#endif

}

char FCD_FAT160_Create_File(char* File_Name, char MSZ_File_Name)
{
	
	#ifdef MX_MIAC_SYSTEM

		unsigned int ModID = ((trisa << 5) + porta) << 9;

		char idx;
		char msg_count, ch;
		char cmd_start = 1;
		char more_data = 1;

		idx = 0;

		// Split string into 6-byte packets
		do
		{
			msg_count = 0;
			do
			{
				ch = File_Name[idx];
				if (ch)
				{
					MIAC_CAN_TX[msg_count] = ch;
					idx = idx + 1;
					msg_count = msg_count + 1;
				}
			}
			while (ch && (msg_count < 6) && (idx < MSZ_File_Name));			// check for 2 x End Of String conditions and packet full

			if (idx == MSZ_File_Name)											// end of string
			{
				more_data = 0;
			}else{
				if (File_Name[idx] == 0) more_data = 0;						// next ch = null
			}

			MIAC_Module_WR(ModID, 743, msg_count,cmd_start,more_data);		// TX data
			MIAC_Module_GetAck(ModID + 32, 743, 255);						// Check for ACK

			cmd_start = 0;
		}
		while (more_data);

		return(MIAC_CAN_RX[0]);

	#else

		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

	#endif

}

char FCD_FAT160_Delete_File(char* File_Name, char MSZ_File_Name)
{
	
	#ifdef MX_MIAC_SYSTEM

		unsigned int ModID = ((trisa << 5) + porta) << 9;

		char idx;
		char msg_count, ch;
		char cmd_start = 1;
		char more_data = 1;

		idx = 0;

		// Split string into 6-byte packets
		do
		{
			msg_count = 0;
			do
			{
				ch = File_Name[idx];
				if (ch)
				{
					MIAC_CAN_TX[msg_count] = ch;
					idx = idx + 1;
					msg_count = msg_count + 1;
				}
			}
			while (ch && (msg_count < 6) && (idx < MSZ_File_Name));			// check for 2 x End Of String conditions and packet full

			if (idx == MSZ_File_Name)											// end of string
			{
				more_data = 0;
			}else{
				if (File_Name[idx] == 0) more_data = 0;						// next ch = null
			}

			MIAC_Module_WR(ModID, 744, msg_count,cmd_start,more_data);		// TX data
			MIAC_Module_GetAck(ModID + 32, 744, 255);						// Check for ACK

			cmd_start = 0;
		}
		while (more_data);

		return(MIAC_CAN_RX[0]);

	#else

		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

	#endif

}

void FCD_FAT160_Write_Byte_To_Buffer(short Address, char Data)
{
	
	#ifdef MX_MIAC_SYSTEM

		unsigned int ModID = ((trisa << 5) + porta) << 9;

		MIAC_CAN_TX[0] = (Address >> 8);
		MIAC_CAN_TX[1] = Address;
		MIAC_CAN_TX[2] = Data;

		MIAC_Module_WR(ModID, 745,3,1,0);
		MIAC_Module_GetAck(ModID + 32, 745, 20);

	#else

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

	#endif

}

char FCD_FAT160_Read_Byte_From_Buffer(short Address)
{
	
	#ifdef MX_MIAC_SYSTEM

		unsigned int ModID = ((trisa << 5) + porta) << 9;

		MIAC_CAN_TX[0] = (Address >> 8);
		MIAC_CAN_TX[1] = Address;

		MIAC_Module_WR(ModID, 746, 2,1,0);
		MIAC_Module_GetAck(ModID + 32, 746, 20);

		return(MIAC_CAN_RX[0]);

	#else

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

	#endif

}

char FCD_FAT160_Open_Folder(char* Folder_Name, char MSZ_Folder_Name)
{
	
	#ifdef MX_MIAC_SYSTEM

		unsigned int ModID = ((trisa << 5) + porta) << 9;

		char idx;
		char msg_count, ch;
		char cmd_start = 1;
		char more_data = 1;

		idx = 0;

		// Split string into 6-byte packets
		do
		{
			msg_count = 0;
			do
			{
				ch = Folder_Name[idx];
				if (ch)
				{
					MIAC_CAN_TX[msg_count] = ch;
					idx = idx + 1;
					msg_count = msg_count + 1;
				}
			}
			while (ch && (msg_count < 6) && (idx < Folder_Name));			// check for 2 x End Of String conditions and packet full

			if (idx == MSZ_Folder_Name)											// end of string
			{
				more_data = 0;
			}else{
				if (Folder_Name[idx] == 0) more_data = 0;						// next ch = null
			}

			MIAC_Module_WR(ModID, 747, msg_count,cmd_start,more_data);		// TX data
			MIAC_Module_GetAck(ModID + 32, 747, 255);						// Check for ACK

			cmd_start = 0;
		}
		while (more_data);

		return(MIAC_CAN_RX[0]);

	#else

	// ".." - 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
				{
					#if	(MX_FAT_TYPE == 1 || MX_FAT_TYPE == 2)
						if (mx_fat_system == 1)
						{
							mx_cluster = FCD_FAT160_Read_Byte_From_Buffer(21 + (i*32));						//Read Cluster of folder start
							mx_cluster = (mx_cluster << 8) | FCD_FAT160_Read_Byte_From_Buffer(20 + (i*32));
						}
					#endif
					mx_cluster = (mx_cluster << 8) | FCD_FAT160_Read_Byte_From_Buffer(27 + (i*32));
					mx_cluster = (mx_cluster << 8) | FCD_FAT160_Read_Byte_From_Buffer(26 + (i*32));

					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

	#endif

}

short FCD_FAT160_Scan_Current_Folder(short Current_Idx, char Scan_Type)
{
	
	#ifdef MX_MIAC_SYSTEM

		unsigned int ModID = ((trisa << 5) + porta) << 9;

		MIAC_CAN_TX[0] = (Current_Idx >> 8);
		MIAC_CAN_TX[1] = Current_Idx;
		MIAC_CAN_TX[2] = Scan_Type;

		MIAC_Module_WR(ModID, 748, 3,1,0);
		MIAC_Module_GetAck(ModID + 32, 748, 255);

		return(MIAC_CAN_RX[0]);

	#else

		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

	#endif

}

char FCD_FAT160_Read_Byte_From_Scan(char idx)
{
	
	#ifdef MX_MIAC_SYSTEM

		unsigned int ModID = ((trisa << 5) + porta) << 9;

		MIAC_CAN_TX[0] = idx;

		MIAC_Module_WR(ModID, 749, 1,1,0);
		MIAC_Module_GetAck(ModID + 32, 749, 20);

		return(MIAC_CAN_RX[0]);

	#else

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

	#endif

}

char FCD_FAT160_MX_SPI_BYTE(char shift)
{
	
	#ifdef MX_MIAC_SYSTEM
		return(0);
	#else
		#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(10);	//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
	#endif
}

char FCD_FAT160_MX_Init_Card()
{
	#ifdef MX_MIAC_SYSTEM
		return(0);
	#else
		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
	#endif
}

char FCD_FAT160_MX_Send_Buffer(long address)
{
	#ifdef MX_MIAC_SYSTEM
		return(0);
	#else
		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
	#endif
}

char FCD_FAT160_MX_Get_Buffer(long address)
{
	
	#ifdef MX_MIAC_SYSTEM
		return(0);
	#else
		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
	#endif
}

void FCD_FAT160_MX_Format_File_String(char* File_Name, char MSZ_File_Name)
{
	#ifndef MX_MIAC_SYSTEM
		unsigned char i,j;
		char temp[12] = {0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20};

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

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

		//FCD_PWM0_SetDutyCycle(1, 0);
		//delay_s(1);

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

		if(temp[i] == '.')											//Find the '.' seperator
		{
			j++;
			for(i=8;i<11 && temp[j] != 0; i++)
			{
				mx_name_ext[i] = temp[j];
				j++;
			}
		}

	#endif
}

void FCD_FAT160_MX_Add_Sector_To_File()
{
	#ifndef MX_MIAC_SYSTEM
		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 = (long) 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;
			}
			#if (MX_FAT_TYPE == 1 || MX_FAT_TYPE == 2)
				if (mx_fat_system == 1)
				{
					fat_pointer = FCD_FAT160_Read_Byte_From_Buffer((idx_fat * SECT_ADDR_LEN) + 3);
					fat_pointer = (fat_pointer << 8) | FCD_FAT160_Read_Byte_From_Buffer((idx_fat * SECT_ADDR_LEN) + 2);
				}
			#endif
			fat_pointer = (fat_pointer << 8) | FCD_FAT160_Read_Byte_From_Buffer((idx_fat * SECT_ADDR_LEN) + 1);
			fat_pointer = (fat_pointer << 8) | FCD_FAT160_Read_Byte_From_Buffer(idx_fat * SECT_ADDR_LEN);
		}

		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), (long)(mx_cluster >> 16));
				FCD_FAT160_Write_Byte_To_Buffer(((idx_fat * SECT_ADDR_LEN) + 3), (long)(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 = (long) 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);
	#endif
}

void FCD_FAT160_MX_Clear_Buffer()
{
	#ifndef MX_MIAC_SYSTEM

		short count;

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

char FCD_FAT160_Read_Next_File_Sector()
{
	#ifdef MX_MIAC_SYSTEM
		return(0);
	#else
		#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;

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


			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
	#endif
}



//PWM(0): //Macro implementations


void FCD_PWM0_Enable(char nIdx)
{
	
	#ifdef MX_MIAC_SYSTEM
	  #if ((-1 & 0x001f) != MX_MIAC_MM_MIAC_BASE)
		#define MX_MIAC_EXTERNAL
	  #endif
	#endif

	#ifdef MX_MIAC_EXTERNAL
		short ModID = (((-1 & 0x0300) << 1) + ((-1 & 0x001f) << 4)) << 5;

		MIAC_CAN_TX[0] = nIdx;
		MIAC_CAN_TX[1] = 255;
		MIAC_CAN_TX[2] = 0x04;
		MIAC_Module_WR(ModID, 320, 3, 1, 0);
		MIAC_Module_GetAck(ModID + 32, 320, 20);

		#undef MX_MIAC_EXTERNAL
	#else

	  #ifndef MX_PWM		//error checking
		#error "This chip does not have PWM capability"
	  #else
		#ifndef MX_PWM_CNT
			#error "FCD file error (no MX_PWM_CNT)"
		#endif
		#if (MX_PWM_CNT < 1)
			#error "FCD file error (MX_PWM_CNT < 1)"
		#endif
		//#if (MX_PWM_CNT > 2)
		//	#error "FCD file error (MX_PWM_CNT > 2)"
		//#endif
		#ifndef MX_PWM_TRIS1
			#error "FCD file error (no MX_PWM_TRIS1)"
		#endif
		#ifndef MX_PWM_1
			#error "FCD file error (no MX_PWM_1)"
		#endif
	    #if (MX_PWM_CNT == 2)
	      	#ifndef MX_PWM_TRIS2
				#error "FCD file error (no MX_PWM_TRIS2)"
	      	#endif
	      	#ifndef MX_PWM_2
				#error "FCD file error (no MX_PWM_2)"
	      	#endif
	    #endif
	    #if (0 == 1)
	      	#ifndef MX_PWM_TRIS1a
				#error "PWM component error (using alternative, but no MX_PWM_TRIS1a)"
	        	#define MX_PWM_ALT_ERROR
	      	#endif
	      	#ifndef MX_PWM_1a
				#error "PWM component error (using alternative, but no MX_PWM_1a)"
	        	#define MX_PWM_ALT_ERROR
	      	#endif
	    #endif
	    #if (0 == 2)
	      	#ifndef MX_PWM_TRIS2a
				#error "PWM component error (using alternative, but no MX_PWM_TRIS2a)"
	  			#define MX_PWM_ALT_ERROR
	      	#endif
	      	#ifndef MX_PWM_2a
				#error "PWM component error (using alternative, but no MX_PWM_2a)"
	        	#define MX_PWM_ALT_ERROR
	      	#endif
	    #endif

	 	#ifdef MX_PWM
			pr2 = 255;
			t2con = 0x04;
		#endif

	  	#if (MX_PWM_CNT >= 1)
			if (nIdx == 1)
			{
				ccp1con = 0x0C;

			  	#if (0 == 1)
			   		#ifndef MX_PWM_ALT_ERROR
						clear_bit(MX_PWM_TRIS1a, MX_PWM_1a);
			   		#endif
			  	#else
					clear_bit(MX_PWM_TRIS1, MX_PWM_1);
			  	#endif
			}
	  	#endif

	  	#if (MX_PWM_CNT >= 2)
			if (nIdx == 2)
			{
				ccp2con = 0x0C;
			  	#if (0 == 2)
			   		#ifndef MX_PWM_ALT_ERROR
						clear_bit(MX_PWM_TRIS2a, MX_PWM_2a);
			   		#endif
			 	#else
					clear_bit(MX_PWM_TRIS2, MX_PWM_2);
			  	#endif
		   }
	  	#endif
	  #endif

	  #ifdef MX_PWM_ALT_ERROR
	   #undef MX_PWM_ALT_ERROR
	  #endif

	#endif

}

void FCD_PWM0_Disable(char nIdx)
{
	
	#ifdef MX_MIAC_SYSTEM
	  #if ((-1 & 0x001f) != MX_MIAC_MM_MIAC_BASE)
		#define MX_MIAC_EXTERNAL
	  #endif
	#endif


	#ifdef MX_MIAC_EXTERNAL
		short ModID = (((-1 & 0x0300) << 1) + ((-1 & 0x001f) << 4)) << 5;

		MIAC_CAN_TX[0] = nIdx;
		MIAC_Module_WR(ModID, 321, 1, 1, 0);
		MIAC_Module_GetAck(ModID, 321, 20);

		#undef MX_MIAC_EXTERNAL

	#else

	 	#ifndef MX_PWM		//error checking
			#error "This chip does not have PWM capability"
	  	#else
		  	#if (MX_PWM_CNT >= 1)
				if (nIdx == 1)
				{
					ccp1con = 0x00;
				}
		  	#endif

		  	#if (MX_PWM_CNT >= 2)
				if (nIdx == 2)
				{
					ccp2con = 0x00;
				}
		  	#endif
	 	#endif
	#endif

}

void FCD_PWM0_SetDutyCycle(char nIdx, char nDuty)
{
	
	#ifdef MX_MIAC_SYSTEM
	  #if ((-1 & 0x001f) != MX_MIAC_MM_MIAC_BASE)
		#define MX_MIAC_EXTERNAL
	  #endif
	#endif

	#ifdef MX_MIAC_EXTERNAL

		short ModID = (((-1 & 0x0300) << 1) + ((-1 & 0x001f) << 4)) << 5;

		MIAC_CAN_TX[0] = nIdx;
		MIAC_CAN_TX[1] = nDuty;
		MIAC_Module_WR(ModID, 322, 2, 1, 0);
		MIAC_Module_GetAck(ModID, 322, 20);

		#undef MX_MIAC_EXTERNAL
	#else

	  //error checking
	  #ifndef MX_PWM
		#error "This chip does not have PWM capability"
	  #else
		  #if (MX_PWM_CNT >= 1)
			if (nIdx == 1)
			{
				ccpr1l = nDuty;
			}
		  #endif

		  #if (MX_PWM_CNT >= 2)
			if (nIdx == 2)
			{
				ccpr2l = nDuty;
			}
		  #endif
	 #endif
	#endif

}

void FCD_PWM0_ChangePeriod(char nPeriodVal, char nPrescalerVal)
{
	
	#ifdef MX_MIAC_SYSTEM
	  #if ((-1 & 0x001f) != MX_MIAC_MM_MIAC_BASE)
		#define MX_MIAC_EXTERNAL
	  #endif
	#endif


	#ifdef MX_MIAC_EXTERNAL

		short ModID = (((-1 & 0x0300) << 1) + ((-1 & 0x001f) << 4)) << 5;

		MIAC_CAN_TX[0] = nPeriodVal;
		MIAC_CAN_TX[1] = nPrescalerVal;
		MIAC_CAN_TX[2] = (nPrescalerVal >> 8);
		MIAC_Module_WR(ModID, 323, 3, 1, 0);
		MIAC_Module_GetAck(ModID, 323, 20);

		#undef MX_MIAC_EXTERNAL
	#else

	  //error checking
	  #ifndef MX_PWM
			#error "This chip does not have PWM capability"
	  #else
	    pr2 = nPeriodVal;

	    switch (nPrescalerVal)
	    {
	        case 1:
	            t2con = 0x04;
	            break;

	        case 4:
	            t2con = 0x05;
	            break;

	        case 16:
	            t2con = 0x06;
	            break;
	    }
	  #endif
	#endif

}

void FCD_PWM0_SetDutyCycle10bit(char nIdx, short nDuty)
{
	
	#ifdef MX_MIAC_SYSTEM
	  #if ((-1 & 0x001f) != MX_MIAC_MM_MIAC_BASE)
		#define MX_MIAC_EXTERNAL
	  #endif
	#endif


	#ifdef MX_MIAC_EXTERNAL

		short ModID = (((-1 & 0x0300) << 1) + ((-1 & 0x001f) << 4)) << 5;

		MIAC_CAN_TX[0] = nIdx;
		MIAC_CAN_TX[2] = nDuty;
		MIAC_CAN_TX[1] = (nDuty >> 8);
		MIAC_Module_WR(ModID, 324, 3, 1, 0);
		MIAC_Module_GetAck(ModID, 324, 20);

		#undef MX_MIAC_EXTERNAL
	#else

		char nCCPxCONtemp;

	  //error checking
	  #ifndef MX_PWM
	  	#error "This chip does not have PWM capability"
	  #else
		  #if (MX_PWM_CNT >= 1)
			if (nIdx == 1)
			{
				ccpr1l = (nDuty & 0x3FC) >> 2;

				nDuty = (nDuty & 0x03) << 4;
				nCCPxCONtemp = (ccp1con & 0xCF) | nDuty;
				ccp1con = nCCPxCONtemp;
			}
		  #endif

		  #if (MX_PWM_CNT >= 2)
			if (nIdx == 2)
			{
				ccpr2l = (nDuty & 0x3FC) >> 2;

				nDuty = (nDuty & 0x03) << 4;
				nCCPxCONtemp = (ccp2con & 0xCF) | nDuty;
				ccp2con = nCCPxCONtemp;
			}
		  #endif
	 #endif
	#endif

}

//Macro implementations

void FCM_Stream_Audio_TMR0_INT()
{
	//Pour éviter les clics de la sortie audio lors de la numérisation pour le secteur suivant un tampon 112 octets de sauvegarde est utilisé pour permettre de continuer l'audio en continu.
	
	//Modify Timer interrupt freq 8KHz
	//C Code:
	tmr0l = 70;



	//Is the sample index in the backup region
	//Decision: idx >= 400?
	if (FCV_IDX >= 400)
	{
		//Read byte from backup buffer
		//Calculation:
		//  temp = idx - 400
		//  sample = buffer[temp]
		FCV_TEMP = FCV_IDX - 400;
		FCV_SAMPLE = FCV_BUFFER[FCV_TEMP];
		

		//Decision
		//Decision: idx = 400?
		if (FCV_IDX == 400)
		{
			//Calculation
			//Calculation:
			//  next_flag = 1
			FCV_NEXT_FLAG = 1;
			

		}


	} else {
		//Read Byte From Buffer
		//Call Component Macro: sample=FAT16(0)::Read_Byte_From_Buffer(idx)
		FCV_SAMPLE = FCD_FAT160_Read_Byte_From_Buffer(FCV_IDX);


	}


	//Output Sample to PWM
	//Call Component Macro: PWM(0)::SetDutyCycle(1, sample)
	FCD_PWM0_SetDutyCycle(1, FCV_SAMPLE);


	//Increment Buffer Index
	//Calculation:
	//  idx = idx + 1
	FCV_IDX = FCV_IDX + 1;
	

	//Is this the end of the buffer
	//Decision: idx = 512?
	if (FCV_IDX == 512)
	{
		//Reset buffer index and set sample flag
		//Calculation:
		//  idx = 0
		FCV_IDX = 0;
		

		//Calculation
		//Calculation:
		//  sample_flag = 1
		FCV_SAMPLE_FLAG = 1;
		

	}


}

void FCM_Fill_Backup_Buffer()
{
	//Remplit le tampon de sauvegarde lorsque la minuterie interrompre est continu les données du tampon normales
	
	//Initialise Backup Buffer
	//Calculation:
	//  idx_buf = 0
	FCV_IDX_BUF = 0;
	

	//Fill Backup Buffer
	//Loop: Loop 112 times
	for (FCLV_LOOP1=0; FCLV_LOOP1<112; FCLV_LOOP1++)
	{
		//Calculate position in backup buffer 400 + 112 = 512
		//Calculation:
		//  temp_address = idx_buf + 400
		FCV_TEMP_ADDRESS = FCV_IDX_BUF + 400;
		

		//Collect Sample from card
		//Call Component Macro: buff_sample=FAT16(0)::Read_Byte_From_Buffer(temp_address)
		FCV_BUFF_SAMPLE = FCD_FAT160_Read_Byte_From_Buffer(FCV_TEMP_ADDRESS);


		//Store sample into backup buffer
		//Calculation:
		//  buffer[idx_buf] = buff_sample
		FCV_BUFFER[FCV_IDX_BUF] = FCV_BUFF_SAMPLE;
		

		//Increment backup buffer index
		//Calculation:
		//  idx_buf = idx_buf + 1
		FCV_IDX_BUF = FCV_IDX_BUF + 1;
		

	}


	//Clear Sample Flag
	//Calculation:
	//  sample_flag = 0
	FCV_SAMPLE_FLAG = 0;
	

}

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

	
	#ifdef MX_MIAC_SYSTEM

	  #define MOD_ID	((trisa << 5) + porta) << 9

		MIAC_Module_WR(MOD_ID, 750, 0,1,0);
		MIAC_Module_GetAck(MOD_ID + 32, 750, 20);

	  #undef MOD_ID
	#else
		#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
				#error "Chip does not have SPI capability"
			#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
	#endif


	//Interrupt initialisation code
	


	//Assign filename
	//String Manipulation:
	//  filename = "fire.wav"
	FCI_CONCATENATE("fire.wav",8,"",0,FCV_FILENAME,FCSZ_FILENAME);
	

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


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


	//Initialise Return Value
	//Calculation:
	//  retval = 1
	FCV_RETVAL = 1;
	

	//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();


	}


	//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: ",12);


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


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


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


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


		//File OK
		//Call Component Macro: LCDDisplay(0)::PrintString("Streaming File")
		FCD_LCDDisplay0_PrintString("Streaming File",14);


		//Initialise Buffer Index
		//Calculation:
		//  idx = 0
		//  Bytes_In_Sect = 512
		//  retval = 0
		//  sample_flag = 1
		//  next_flag = 0
		FCV_IDX = 0;
		FCV_BYTES_IN_SECT = 512;
		FCV_RETVAL = 0;
		FCV_SAMPLE_FLAG = 1;
		FCV_NEXT_FLAG = 0;
		

		//Call Component Macro
		//Call Component Macro: PWM(0)::Enable(1)
		FCD_PWM0_Enable(1);


		//Interrupt
		//Interrupt: Enable TMR0
		cr_bit(t0con, T0CS);
		st_bit(t0con, T0SE);
		t0con = (t0con & 0xF0) | 0x02;
		st_bit(intcon, GIE);
		st_bit(intcon, TMR0IE);


		//Loop
		//Loop: While 1
		while (1)
		{
			//Decision
			//Decision: sample_flag = 1?
			if (FCV_SAMPLE_FLAG == 1)
			{
				//Fill up backup buffer
				//Call Macro: Fill_Backup_Buffer
				FCM_Fill_Backup_Buffer();


				//Read number of bytes in sector
				//Call Component Macro: Bytes_In_Sect=FAT16(0)::Read_File_Length
				FCV_BYTES_IN_SECT = FCD_FAT160_Read_File_Length();


			}


			//Is the sample index in the backup region
			//Decision: next_flag = 1?
			if (FCV_NEXT_FLAG == 1)
			{
				//Try to move to the next disk sector
				//Call Component Macro: retval=FAT16(0)::Move_To_Next_File_Sector(0)
				FCV_RETVAL = FCD_FAT160_Move_To_Next_File_Sector(0);


				//end sector reached?
				//Decision: retval = 1?
				if (FCV_RETVAL == 1)
				{
					//Goto Connection Point
					//Goto Connection Point: [A]: A
					goto FCC_Main_A;


				} else {
					//Next sector has been reached
					//Calculation:
					//  next_flag = 0
					FCV_NEXT_FLAG = 0;
					

				}


			}


			//Is the end of the file data reached
			//Decision: Bytes_In_Sect <= idx?
			if (FCV_BYTES_IN_SECT <= FCV_IDX)
			{
				//Goto Connection Point
				//Goto Connection Point: [A]: A
				goto FCC_Main_A;


			}


		}


		//End Of File Reached
		//Connection Point: [A]: A
FCC_Main_A:
;


		//Interrupt
		//Interrupt: Disable TMR0
		cr_bit(intcon, TMR0IE);


		//Call Component Macro
		//Call Component Macro: PWM(0)::Disable(1)
		FCD_PWM0_Disable(1);


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


		//Print EOF reached
		//Call Component Macro: LCDDisplay(0)::PrintString("EOF Reached")
		FCD_LCDDisplay0_PrintString("EOF Reached",11);


	}


	mainendloop: goto mainendloop;
}

void MX_INTERRUPT_MACRO(void)
{
	//Handler code for [TMR0]
	#ifndef MX_INTHANDLER_intcon_TMR0IF
	#define MX_INTHANDLER_intcon_TMR0IF
	if (ts_bit(intcon, TMR0IF) && ts_bit(intcon, TMR0IE))
	{
		#ifdef USE_FLOWCODE_ICD
			extern char ICD_Interrupt_Enable = 1;
		#endif	
		FCM_Stream_Audio_TMR0_INT();
		cr_bit(intcon, TMR0IF);
		#ifdef USE_FLOWCODE_ICD
			extern char ICD_Interrupt_Enable = 0;
		#endif	
	}
	#else
	#warning "This interrupt has previously been enabled, so the macro <Stream_Audio_TMR0_INT> may never get called."
	#endif


}



