/*********************************************************************
 *                    Flowcode RF Component Code
 *
 * File: RF.c
 *
 * (c) 2010 Matrix Multimedia Ltd.
 * http://www.matrixmultimedia.com
 *
 * Software License Agreement
 *
 * The software supplied herewith by Matrix Multimedia Ltd (the
 * “Company”) for its Flowcode graphical programming language is
 * intended and supplied to you, the Company’s customer, for use
 * solely and exclusively on the Company's products. The software
 * is owned by the Company, and is protected under applicable
 * copyright laws. All rights are reserved. Any use in violation
 * of the foregoing restrictions may subject the user to criminal
 * sanctions under applicable laws, as well as to civil liability
 * for the breach of the terms and conditions of this licence.
 *
 * THIS SOFTWARE IS PROVIDED IN AN “AS IS” CONDITION. NO WARRANTIES,
 * WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
 * TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
 * IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
 * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
 *
 * Changelog:
 *
 *  date  | by | description
 * -------+----+-----------------------------------------------------
 * 201010 | BR | Created
 * 140111 | BR | Modification to code to fix a number of minor definition bugs
 * 110411 | ST | Major rewrite based on AVR code from SK
 * 090511 | BR | Updated to Seans latest version of the component
 * 220711 | BR | Fixed an issue with the RF port DDR being named TRIS
 * 240711 | SK | Fixed timing and shifting errors in code for software SPI.
 * 281011 | BR | Converted to Universal RF Component Code File
 * 011211 | BR | Updated FC_CAL_Bit functions
 * 021211 | BR | Converted to new dynamic defines mechanism
 ********************************************************************/

/*********************************************************************

 Return & parameter types:
   void
   MX_UINT8
   MX_SINT16
   MX_STRING

 Pin directions:
   0 = OUTPUT
   2 = INPUT
   3 = BIDIRECTIONAL

**********************************************************************

[Settings]
CLSID={065099EC-6FF8-4DB4-BEDE-B96B09787B31}
IsAnalogue=0
MultipleAllowed=0
Description=RF Flowcode Component

**********************************************************************

[Port]
DesiredPort=0
PortMandatory=0
SamePortAsID=0

[Pins]
Count=0

[PinPort]
# PORTA = 0
# PORTB = 1
# PORTC = 2
# PORTD = 3
# PORTE = 4

[PinDesiredBit]

[PinDirection]
# DIR_INPUT = 2
# DIR_OUTPUT = 0
# DIR_BIDIRECTIONAL = 3

[PinMustUsePort]
# boolean

[SamePortAsPinX]
# -1 = any pin
# otherwise, the pin number

[PinMustUsePin]
# boolean

[PinValue]
# boolean (0 = off, 1 = on)

**********************************************************************

[MacroNames]
Count=24
1=SPI_Byte16
2=SPI_Command
3=Wait_For_SDI
4=Init_RF_Module
5=Uninit_RF_Module
6=Send_Byte
7=Send_String
8=Receive_Byte
9=Receive_String
10=Activate_RX_Mode
11=Activate_TX_Mode
12=Update_Centre_Frequency
13=Set_Sync_Pattern
14=RX_Tune
15=TX_Tune
16=Set_Data_Rate
17=Read_RX_Signal_Strength
18=FSK_Write
19=FSK_Read
20=Set_Buffer_Data
21=Send_Buffer
22=Check_Buffer
23=Get_Data_Count
24=Get_Buffer_Data

[MacroReturns]
1=void
2=MX_SINT16
3=void
4=MX_SINT16
5=void
6=void
7=void
8=MX_UINT8
9=MX_STRING
10=void
11=void
12=void
13=void
14=void
15=void
16=void
17=MX_UINT8
18=void
19=MX_UINT8
20=void
21=void
22=MX_UINT8
23=MX_UINT8
24=MX_UINT8

[MacroIsPrivate]
1=1
2=1
3=1
4=0
5=0
6=0
7=0
8=0
9=0
10=1
11=1
12=0
13=0
14=0
15=0
16=0
17=0
18=0
19=0
20=0
21=0
22=0
23=0
24=0

[MacroParameters_SPI_Byte16]
Count=1
1=spicmd

[MacroParamTypes_SPI_Byte16]
1=MX_SINT16

[MacroParameters_SPI_Command]
Count=1
1=spicmd

[MacroParamTypes_SPI_Command]
1=MX_SINT16

[MacroParameters_Wait_For_SDI]
Count=0

[MacroParamTypes_Wait_For_SDI]

[MacroParameters_Init_RF_Module]
Count=0

[MacroParamTypes_Init_RF_Module]

[MacroParameters_Uninit_RF_Module]
Count=0

[MacroParamTypes_Uninit_RF_Module]

[MacroParameters_Send_Byte]
Count=1
1=Data

[MacroParamTypes_Send_Byte]
1=MX_UINT8

[MacroParameters_Send_String]
Count=1
1=String

[MacroParamTypes_Send_String]
1=MX_STRING

[MacroParameters_Receive_Byte]
Count=1
1=Timeout

[MacroParamTypes_Receive_Byte]
1=MX_UINT8

[MacroParameters_Receive_String]
Count=2
1=Length
2=Timeout

[MacroParamTypes_Receive_String]
1=MX_UINT8
2=MX_UINT8

[MacroParameters_Activate_RX_Mode]
Count=0

[MacroParamTypes_Activate_RX_Mode]

[MacroParameters_Activate_TX_Mode]
Count=0

[MacroParamTypes_Activate_TX_Mode]

[MacroParameters_Update_Centre_Frequency]
Count=1
1=Frequency

[MacroParamTypes_Update_Centre_Frequency]
1=MX_SINT16

[MacroParameters_Set_Sync_Pattern]
Count=2
1=Mode
2=Pattern

[MacroParamTypes_Set_Sync_Pattern]
1=MX_UINT8
2=MX_UINT8

[MacroParameters_RX_Tune]
Count=3
1=Bandwidth
2=Gain
3=Threshold

[MacroParamTypes_RX_Tune]
1=MX_UINT8
2=MX_UINT8
3=MX_UINT8

[MacroParameters_TX_Tune]
Count=2
1=Deviation
2=Power

[MacroParamTypes_TX_Tune]
1=MX_UINT8
2=MX_UINT8

[MacroParameters_Set_Data_Rate]
Count=1
1=Rate

[MacroParamTypes_Set_Data_Rate]
1=MX_UINT8

[MacroParameters_Read_RX_Signal_Strength]
Count=0

[MacroParamTypes_Read_RX_Signal_Strength]

[MacroParameters_FSK_Write]
Count=1
1=State

[MacroParamTypes_FSK_Write]
1=MX_UINT8

[MacroParameters_FSK_Read]
Count=0

[MacroParamTypes_FSK_Read]

[MacroParameters_Set_Buffer_Data]
Count=2
1=Index
2=Data

[MacroParamTypes_Set_Buffer_Data]
1=MX_UINT8
2=MX_UINT8

[MacroParameters_Send_Buffer]
Count=1
1=Count

[MacroParamTypes_Send_Buffer]
1=MX_UINT8

[MacroParameters_Check_Buffer]
Count=1
1=Timeout

[MacroParamTypes_Check_Buffer]
1=MX_UINT8

[MacroParameters_Get_Data_Count]
Count=0

[MacroParamTypes_Get_Data_Count]

[MacroParameters_Get_Buffer_Data]
Count=1
1=Index

[MacroParamTypes_Get_Buffer_Data]
1=MX_UINT8

 ********************************************************************/

/********************************************************************
 * ADDITIONAL CODE
 ********************************************************************/

/*DefinesCode_Start*/

/**** Macro Substitutions ****
a = Unique Reference
b = SPI Channel 0-SW / 1-HW SPI1 / 2-HW SPI2 / 3-HW SPI3 ....
c = MOSI Pin
d = MOSI Port
e = MISO Pin
f = MISO Port
g = SCK Pin
h = SCK Port
i = CS Pin
j = CS Port
k = FSEL Pin
l = FSEL Port
m = Frequency Selection	1-433MHz  2-868MHz 3-915MHz
n = Centre Frequency 		Channel selection - 96-3903	See Calculation p28
o = Baud Rate 				See Calculation p37
p = Receiver Bandwidth
q = Receiver Gain
r = Receiver Threshold
s = Transmitter Deviation
t = Transmitter Power Output
u = Transmitter Duty Cycle Setting
v = Data Mode
w = Preamble Sync ID Value
x = Extended Preamble Sync ID Enable
******************************/

#define MX_RF_CHANNEL		%b

//Definitions for SDI control - need access to spi pin in application
#if (MX_RF_CHANNEL == 0)			//software spi
#define %a_MX_RF_SDI_PIN			%e
#define %a_MX_RF_SDI_PORT			port%f
#define %a_MX_RF_SDI_TRIS			tris%f
#endif
#if (MX_RF_CHANNEL == 1)			//channel 1
#define %a_MX_RF_SDI_PIN			MX_SPI_1_MISO_PIN
#define %a_MX_RF_SDI_PORT			MX_SPI_1_MISO_PORT
#define %a_MX_RF_SDI_TRIS			MX_SPI_1_MISO_TRIS
#endif
#if (MX_RF_CHANNEL == 2)			//channel 2
#define %a_MX_RF_SDI_PIN			MX_SPI_2_MISO_PIN
#define %a_MX_RF_SDI_PORT			MX_SPI_2_MISO_PORT
#define %a_MX_RF_SDI_TRIS			MX_SPI_2_MISO_TRIS
#endif

//Definitions for CS control
#define %a_MX_RF_CS_PIN				%i
#define %a_MX_RF_CS_PORT			port%j
#define %a_MX_RF_CS_TRIS			tris%j

//Definitions for FSEL Pin
#define %a_MX_RF_FSEL_PIN			%k
#define %a_MX_RF_FSEL_PORT			port%l
#define %a_MX_RF_FSEL_TRIS			tris%l

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

#define %a_SPI_Master_Init	CAL_APPEND(FC_CAL_SPI_Master_Init_, %a_MX_SPI_UREF)
#define %a_SPI_Master_Byte	CAL_APPEND(FC_CAL_SPI_Master_Byte_, %a_MX_SPI_UREF)

extern void %a_SPI_Master_Init ();
extern MX_UINT8 %a_SPI_Master_Byte (MX_UINT8 DataOut);

//Duty cycle limit when using the 868MHz band in Europe!!!

//common defines
#define MX_RF_FREQ  	%m							//Module Frequency
#define MX_RF_CFREQ		%n							//Central Frequency 96 <-> 3903		(0x7D0)
#define MX_RF_BAUD		%o							//Data Baud Rate					(0x23)
#define MX_RF_BWIDTH	(%p + 1)					//Bandwithd 0= / 6=
#define MX_RF_GAIN		%q							//Gain 0= / 3=
#define MX_RF_THRESH	%r							//Threshold 0= / 5=
#define MX_RF_DVN		%s							//Deviation 0=15KHz / 15=240KHz
#define MX_RF_PWR		%t							//Power 0=0dB / 7=-17.5dB
#define MX_RF_DUTY		%u
#define MX_RF_DATAMODE	%v							//Data mode - I/O or Data
#define MX_RF_ID		%w							//Sync ID
#define MX_RF_EXTID		((1 - %x) * 8)				//Extended Sync 0=Off / 1=On
#define MX_RF_TXPROP	((MX_RF_DVN << 4) | MX_RF_PWR)

#define MX_RF_BUFFER_MAX	8

// General commands
#define GENCREG 	(0x8008 | (MX_RF_FREQ << 4))	//RF_Frequency does not change....
#define PMCREG 		0x8200
#define CFSREG		0xA000

// Data commands
#define DATARATE	0xC600
#define SYNCHRON	0xCE00

// RX commands
#define RXCREG 		0x9000
#define RXBREG		0xB000
#define FIFORSTREG	0xCA81		//0xCA85
#define BBFCREG 	0xC22C
#define AFCCREG		0xC4D7

// TX commands
#define TXCREG		0x9800
#define TXBREG 		0xB800

// Preloaded commands with data

#define PDOWN		0x8201

MX_UINT8 MX_RF_Mode;
MX_UINT8 MX_RF_Sync = MX_RF_ID;
MX_UINT8 MX_RF_RX_Buffer[MX_RF_BUFFER_MAX + 2];
MX_UINT8 MX_RF_RX_Buff1[MX_RF_BUFFER_MAX + 2];
MX_UINT8 MX_RF_TX_Buffer[MX_RF_BUFFER_MAX + 2];

/*DefinesCode_End*/

/*InitialisationCode_Start*/
/*InitialisationCode_End*/

/*InterruptCode_Start*/
/*InterruptCode_End*/

/********************************************************************
 * FUNCTIONS
 ********************************************************************/


void SPI_Byte16(MX_SINT16 spicmd)
{
/*Macro_SPI_Byte16_Start*/

	unsigned char temp;

	temp = spicmd >> 8;
	%a_SPI_Master_Byte(temp);			// Send Upper Command Byte
	temp = spicmd & 0xFF;
	%a_SPI_Master_Byte(temp);			// Send Lower Command Byte

/*Macro_SPI_Byte16_End*/
}


MX_SINT16 SPI_Command(MX_SINT16 spicmd)
{
/*Macro_SPI_Command_Start*/

	unsigned int retval;
	unsigned char temp;

	FC_CAL_Bit_Low(%a_MX_RF_CS_PORT, %a_MX_RF_CS_PIN);										// Clear Chip Select bit
	delay_us(1);
	temp = spicmd >> 8;
	retval = %a_SPI_Master_Byte(temp);						// Send Upper Command Byte
	retval = retval << 8;
	temp = spicmd & 0xFF;
	retval = retval | %a_SPI_Master_Byte(temp);				// Send Lower Command Byte
	delay_us(1);
	FC_CAL_Bit_High(%a_MX_RF_CS_PORT, %a_MX_RF_CS_PIN);										// Set Chip Select bit
	delay_us(1);
	return retval;

/*Macro_SPI_Command_End*/
}


void Wait_For_SDI (void)
{
/*Macro_Wait_For_SDI_Start*/

	while(FC_CAL_Bit_In(%a_MX_RF_SDI_PORT, %a_MX_RF_SDI_PIN) == 0);						//Wait for SDI Input

/*Macro_Wait_For_SDI_End*/
}


MX_SINT16 Init_RF_Module()
{
/*Macro_Init_RF_Module_Start*/

	unsigned int Retval;

	FC_CAL_Bit_High_DDR(%a_MX_RF_CS_PORT, %a_MX_RF_CS_TRIS, %a_MX_RF_CS_PIN);								//Setup CS Pin

	%a_SPI_Master_Init();											//Call SPI initialise function

	delay_ms(100);										//100ms Delay to ensure transceiver has powered up

	// Configuring the RF link
	SPI_Command(FIFORSTREG);							//Disable (Sensitive) Reset Mode
	SPI_Command(FIFORSTREG | MX_RF_EXTID | 0x02);		//Restart Synchronous MX_UINT8acter pattern recognition
	SPI_Command(GENCREG);								//Assign frequency band and set load capacitance
	SPI_Command(CFSREG  | MX_RF_CFREQ);					//Set Channel Center Frequency
	SPI_Command(DATARATE | MX_RF_BAUD);					//Set Data Rate
	SPI_Command(PMCREG);								//Turn Off TX and RX controller chains

	Retval = (MX_RF_BWIDTH << 5) | (MX_RF_GAIN << 3) | MX_RF_THRESH;
	SPI_Command(RXCREG | Retval);						//Enable Data RX Output / Set signal strengths and gain

	SPI_Command(SYNCHRON | MX_RF_Sync);
	SPI_Command(TXCREG | MX_RF_TXPROP);					//Set TX frequency deviation

	// Antenna Tuning
	SPI_Command( PMCREG | 0x0020);						//Turn on TX baseband circuit
	delay_ms(5);										//Wait for oscillatr to stabilise

	// Set Up The Receiver
	SPI_Command(PMCREG | 0x0080);						//Turn off Tx, turn on receiver

	Retval = SPI_Command(0);							//Read back and return STSREG
	Retval = SPI_Command(0);							//Read back and return STSREG
	Retval = SPI_Command(0);							//Read back and return STSREG
	Retval = SPI_Command(0);							//Read back and return STSREG
	Retval = SPI_Command(0);							//Read back and return STSREG

  #if (MX_RF_DATAMODE == 0)

	SPI_Command(GENCREG | 0x0040);						//Enable the FIFO
	SPI_Command(FIFORSTREG);
	SPI_Command(FIFORSTREG | MX_RF_EXTID | 0x02);		//Restart Synchronous character pattern recognition
	FC_CAL_Bit_High_DDR(%a_MX_RF_FSEL_PORT, %a_MX_RF_FSEL_TRIS, %a_MX_RF_FSEL_PIN);
	MX_RF_Mode = 0;

  #else

	FC_CAL_Bit_In_DDR(%a_MX_RF_FSEL_PORT, %a_MX_RF_FSEL_TRIS, %a_MX_RF_FSEL_PIN);
	SPI_Command(GENCREG);								//Leave the FIFO disabled
	MX_RF_Mode = 2;

  #endif

	return (Retval);

/*Macro_Init_RF_Module_End*/
}


void Uninit_RF_Module (void)
{
/*Macro_Uninit_RF_Module_Start*/

	SPI_Command(PDOWN);

/*Macro_Uninit_RF_Module_End*/
}


void Send_Byte (MX_UINT8 Data)
{
/*Macro_Send_Byte_Start*/

	Set_Buffer_Data(0, Data);					//Pass byte into send buffer
	Send_Buffer(1);								//Send buffer

/*Macro_Send_Byte_End*/
}


void Send_String (MX_STRING String, MX_UINT8 MSZ_String)
{
/*Macro_Send_String_Start*/

	MX_UINT8 Ptr;
	MX_UINT8 Length;

	Length = MSZ_String;

	for (Ptr = 0; Ptr < Length; Ptr++)		//For each character in string
	{
		Set_Buffer_Data(Ptr, String[Ptr]);	//Pass string into send buffer

		if (String[Ptr] == 0)				//Is there a null byte in the string?
			Length = Ptr;					//If so then we are at the end
	}
	Send_Buffer(Length);					//Send buffer

/*Macro_Send_String_End*/
}


MX_UINT8 Receive_Byte (MX_UINT8 Timeout)
{
/*Macro_Receive_Byte_Start*/

	MX_UINT8 retVal;

	retVal = Check_Buffer(Timeout);				//Check for incoming data

	if (retVal == 1)							//If 1 byte received
		retVal = Get_Buffer_Data(0);			//Collect byte
	else
		return 255;								//Or return timeout err

	return retVal;

/*Macro_Receive_Byte_End*/
}


void Receive_String (MX_STRING FCR_RETVAL, MX_UINT8 FCR_RETVAL_SIZE, MX_UINT8 Length, MX_UINT8 Timeout)
{
/*Macro_Receive_String_Start*/

	MX_UINT8 dcount, idx;

	FCR_RETVAL[0] = 0;											//Begin by assigning null to string

	dcount = Check_Buffer(Timeout);								//Check for incoming data

	if (dcount < 250)											//Valid packet size received?
	{
		for (idx = 0; idx < Length; idx++)						//Loop through specified received bytes
		{
			if (idx < FCR_RETVAL_SIZE)							//Is there still room in the buffer?
			{
				if (idx < dcount)								//Have we received all available bytes?
				{
					FCR_RETVAL[idx] = Get_Buffer_Data(idx);		//Collect byte and add to string

					if (FCR_RETVAL[idx] == 0)					//If null byte received
						Length = idx;							//Finish collecting bytes
				}
			}
		}

		if (idx < FCR_RETVAL_SIZE)								//If string is not full
			FCR_RETVAL[idx] = 0;								//Then add a null byte just incase there was not one in the received data
	}

/*Macro_Receive_String_End*/
}


void Activate_RX_Mode (void)
{
/*Macro_Activate_RX_Mode_Start*/

	SPI_Command(PMCREG | 0x0080);			// turn off Tx, turn on the receiver

	if (MX_RF_Mode == 0)					// Set system mode value
	{
		SPI_Command(GENCREG | 0x0040);		// disable the Tx register, Enable the FIFO

		SPI_Command(FIFORSTREG);
		SPI_Command(FIFORSTREG | MX_RF_EXTID | 0x0002);					//Reset FIFO

		FC_CAL_Bit_High_DDR(%a_MX_RF_FSEL_PORT, %a_MX_RF_FSEL_TRIS, %a_MX_RF_FSEL_PIN);		//FSEL pin as output
	}
	else
	{
		FC_CAL_Bit_In_DDR(%a_MX_RF_FSEL_PORT, %a_MX_RF_FSEL_TRIS, %a_MX_RF_FSEL_PIN);		//FSEL pin as input
		SPI_Command(GENCREG);											//Leave the FIFO disabled
	}

/*Macro_Activate_RX_Mode_End*/
}


void Activate_TX_Mode (void)
{
/*Macro_Activate_TX_Mode_Start*/

	SPI_Command(PMCREG);					// Turn off the transmitter and receiver

	if (MX_RF_Mode == 1)
	{
		SPI_Command(GENCREG | 0x0080);		// Enable the Tx register
	}
	else
	{
		SPI_Command(GENCREG);				// disable the Tx register and the FIFO
	}

	SPI_Command(PMCREG | 0x0020);			// Turn on tx

	FC_CAL_Bit_High_DDR(%a_MX_RF_FSEL_PORT, %a_MX_RF_FSEL_TRIS, %a_MX_RF_FSEL_PIN);		//FSEL pin as output

/*Macro_Activate_TX_Mode_End*/
}


void Update_Centre_Frequency (MX_SINT16 Frequency)
{
/*Macro_Update_Centre_Frequency_Start*/

	if (Frequency < 96)
		Frequency = 96;

	if (Frequency > 3903)
		Frequency = 3903;

	SPI_Command(CFSREG | Frequency);

/*Macro_Update_Centre_Frequency_End*/
}


void Set_Sync_Pattern (MX_UINT8 Mode, MX_UINT8 Pattern)
{
/*Macro_Set_Sync_Pattern_Start*/

	MX_RF_Sync = Pattern;

	FCD_RF0_SPI_Command(FIFORSTREG);

	if (Mode)
	{
		//Word type synchronisation
		SPI_Command(FIFORSTREG | 0x02);
	}
	else
	{
		//Byte type synchronisation
		SPI_Command(FIFORSTREG | 0x0a);
	}
	SPI_Command(SYNCHRON | MX_RF_Sync);

/*Macro_Set_Sync_Pattern_End*/
}


void RX_Tune (MX_UINT8 Bandwidth, MX_UINT8 Gain, MX_UINT8 Threshold)
{
/*Macro_RX_Tune_Start*/

	unsigned int TuneVals;

	if (Bandwidth > 6)
		Bandwidth = 6;

	if (Bandwidth < 1)
		Bandwidth = 1;

	if (Gain > 3)
		Gain = 3;

	if (Threshold > 5)
		Threshold = 5;

	TuneVals = RXCREG;
	TuneVals = TuneVals | (Bandwidth << 5);
	TuneVals = TuneVals | (Gain << 3);
	TuneVals = TuneVals | Threshold;

	SPI_Command(TuneVals);

/*Macro_RX_Tune_End*/
}


void TX_Tune (MX_UINT8 Deviation, MX_UINT8 Power)
{
/*Macro_TX_Tune_Start*/

	MX_UINT8 MX_RF_TxProps;

	if (Deviation > 15)
		Deviation = 15;

	if (Power > 7)
		Power = 7;

	MX_RF_TxProps = Deviation << 4;
	MX_RF_TxProps = MX_RF_TxProps | Power;

	SPI_Command(TXCREG | MX_RF_TxProps);

/*Macro_TX_Tune_End*/
}


void Set_Data_Rate (MX_UINT8 Rate)
{
/*Macro_Set_Data_Rate_Start*/

	MX_UINT8 cs = 0;
	unsigned long r;

	r = 100000 / (29 * Rate);			//10 x data rate value
	r = r + 5;							//round up
	r = r / 10;							//divide by 10

	if (r > 0x80)						//result too large
	{
		cs = 0x80;						//set cs bit
		r >>= 2;						//divide by 4
		if (r & 0x01)
			r = r + 1;					//round up
		r >>= 1;						//divide by 2
	}
	r = r - 1;

	SPI_Command(DATARATE | cs | (MX_UINT8)r);

/*Macro_Set_Data_Rate_End*/
}


MX_UINT8 Read_RX_Signal_Strength (void)
{
/*Macro_Read_RX_Signal_Strength_Start*/

	unsigned int test = 0;

	test = SPI_Command(0);					//Read back and return STSREG
	test = test >> 6;						//Rotate so that data we want is one bits 0 and 1
	test = test & 0x07;						//Mask off any unwanted values

	return (test);

/*Macro_Read_RX_Signal_Strength_End*/
}

void FSK_Write (MX_UINT8 State)
{
/*Macro_FSK_Write_Start*/

	if(MX_RF_Mode != 3)
	{
		MX_RF_Mode = 3;							//Set system mode value
		Activate_TX_Mode();
	}

	if(State)
		FC_CAL_Bit_High(%a_MX_RF_FSEL_PORT, %a_MX_RF_FSEL_PIN);
	else
		FC_CAL_Bit_Low(%a_MX_RF_FSEL_PORT, %a_MX_RF_FSEL_PIN);

/*Macro_FSK_Write_End*/
}

MX_UINT8 FSK_Read (void)
{
/*Macro_FSK_Read_Start*/

	if (MX_RF_Mode != 2)
	{
		MX_RF_Mode = 2;
		Activate_RX_Mode();
	}
	return(FC_CAL_Bit_In(%a_MX_RF_FSEL_PORT, %a_MX_RF_FSEL_PIN));

/*Macro_FSK_Read_End*/
}


void Set_Buffer_Data (MX_UINT8 Index, MX_UINT8 Data)
{
/*Macro_Set_Buffer_Data_Start*/

	if (Index < MX_RF_BUFFER_MAX)
		MX_RF_TX_Buffer[Index + 1] = Data;

/*Macro_Set_Buffer_Data_End*/
}

void Send_Buffer (MX_UINT8 Count)
{
/*Macro_Send_Buffer_Start*/

	MX_UINT8 Data;
	MX_UINT8 Ptr;
	MX_UINT8 NextByte = 1;
	MX_UINT8 Csum = 0;

	if (Count < MX_RF_BUFFER_MAX)
	{
		MX_RF_TX_Buffer[0] = Count;

		//Calculate checksum
		for(Ptr = 0; Ptr <= Count; Ptr++)
			Csum ^= MX_RF_TX_Buffer[Ptr];

		MX_RF_TX_Buffer[Ptr] = Csum;

		//Include count and checksum
		Count += 2;

		//Set Tx mode
		if (MX_RF_Mode != 1)		//If we are in receive mode
		{
			MX_RF_Mode = 1;
			Activate_TX_Mode();		//Switch to transmit mode
		}

		FC_CAL_Bit_High(%a_MX_RF_FSEL_PORT, %a_MX_RF_FSEL_PIN);		// FSEL Output 1
		FC_CAL_Bit_Low(%a_MX_RF_CS_PORT, %a_MX_RF_CS_PIN);			// Clear Chip Select bit
		delay_us(1);

//		Wait_For_SDI();
		SPI_Byte16(TXBREG | 0xAA);				// preamble

  	  #if (MX_RF_EXTID == 0)
		Wait_For_SDI();							//Wait for SDI Input
		SPI_Byte16(TXBREG | 0x2D);				// sync pattern 1st byte (optional)
  	  #endif

		Wait_For_SDI();							//Wait for SDI Input
		SPI_Byte16(TXBREG | MX_RF_Sync);		// sync pattern 2nd byte

		Ptr = 0;

		Data = MX_RF_TX_Buffer[Ptr++];

		while(NextByte)
		{
			Wait_For_SDI();						//Wait for SDI Input
			SPI_Byte16(TXBREG | Data);			// write byte to tx register

			Data = MX_RF_TX_Buffer[Ptr];

			if(Ptr == Count)
				NextByte = 0;

			Ptr++;
		}

		Wait_For_SDI();							//Wait for SDI Input
		SPI_Byte16(TXBREG | 0x00);				// write a dummy byte since the previous byte is still in buffer

		Wait_For_SDI();							//Wait for SDI Input

		FC_CAL_Bit_High(%a_MX_RF_CS_PORT, %a_MX_RF_CS_PIN);		// Chip select high, end transmission

		MX_RF_Mode = 0;
		Activate_RX_Mode();								//Switch to receive mode
	}

/*Macro_Send_Buffer_End*/
}

MX_UINT8 Check_Buffer(MX_UINT8 Timeout)
{
/*Macro_Check_Buffer_Start*/

	MX_UINT8 ByteRx, Data;
	MX_UINT8 LoopCount;
	MX_UINT8 Ptr = 0;
	MX_UINT8 NextByte = 1;
	MX_UINT8 Count;
	MX_UINT8 retVal = 255;					//Nothing Received
	MX_UINT8 bCount = 0;
	MX_UINT8 Csum = 0;

	/*	Return values
		255 = No data
		254 = Count error (data count > buffer)
		253 = Insufficient data/timeout during reception
		252 = Checksum error
	*/

	if (MX_RF_Mode != 0)					//If we are in transmit mode
	{
		MX_RF_Mode = 0;
		Activate_RX_Mode();					//Switch to receive mode
	}

	//Get data count

	LoopCount = 0;
	ByteRx = 0;

	while((LoopCount < Timeout) && (ByteRx == 0))
	{
		FC_CAL_Bit_Low(%a_MX_RF_CS_PORT, %a_MX_RF_CS_PIN);			// Clear Chip Select bit
		delay_us(1);
		ByteRx = FC_CAL_Bit_In(%a_MX_RF_SDI_PORT, %a_MX_RF_SDI_PIN);
		FC_CAL_Bit_High(%a_MX_RF_CS_PORT, %a_MX_RF_CS_PIN);			// Set Chip Select bit

		if (ByteRx == 0)
			delay_us(100);

		LoopCount++;
	}

	if(ByteRx)
	{
		retVal = 254;												// Count received but nothing else
		FC_CAL_Bit_Low(%a_MX_RF_FSEL_PORT, %a_MX_RF_FSEL_PIN);		// FSEL Output 0
		delay_us(1);

		Count = %a_SPI_Master_Byte(0);

		FC_CAL_Bit_High(%a_MX_RF_FSEL_PORT, %a_MX_RF_FSEL_PIN);		// FSEL Output 1

		if (Count <= MX_RF_BUFFER_MAX)
		{
			retVal = 253;											// Count and some data received but packet incomplete
			MX_RF_RX_Buff1[Ptr++] = Count;

			Count = Count + 2;		//Include count and checksum

			while(NextByte)
			{
				LoopCount = 0;
				ByteRx = 0;

				while((LoopCount < Timeout) && (ByteRx == 0))
				{
					FC_CAL_Bit_High(%a_MX_RF_FSEL_PORT, %a_MX_RF_FSEL_PIN);		// FSEL Output 1
					delay_us(1);

					FC_CAL_Bit_Low(%a_MX_RF_CS_PORT, %a_MX_RF_CS_PIN);			// Clear Chip Select bit
					delay_us(1);

					ByteRx = FC_CAL_Bit_In(%a_MX_RF_SDI_PORT, %a_MX_RF_SDI_PIN);

					FC_CAL_Bit_High(%a_MX_RF_CS_PORT, %a_MX_RF_CS_PIN);			// Set Chip Select bit

					if (ByteRx == 0)
					{
						delay_us(100);
					}
					LoopCount = LoopCount + 1;
				}

				if(ByteRx)
				{
					FC_CAL_Bit_Low(%a_MX_RF_FSEL_PORT, %a_MX_RF_FSEL_PIN);		// FSEL Output 0
					delay_us(1);

					MX_RF_RX_Buff1[Ptr++] = %a_SPI_Master_Byte(0);

					bCount = 0;
				}
				else
				{
					bCount = bCount + 1;
					if (bCount == 100)
						NextByte = 0;
				}

				if(Ptr == Count)
				{
					NextByte = 0;

					for(Ptr = 0; Ptr < (Count - 1); Ptr++)
					{
						MX_RF_RX_Buffer[Ptr] = MX_RF_RX_Buff1[Ptr];
						Csum ^= MX_RF_RX_Buffer[Ptr];
					}

					if (Csum == MX_RF_RX_Buff1[Ptr])					//Is checksum ok?
						retVal = Count - 2;
					else
					{
						MX_RF_RX_Buffer[1] = Csum;
						retVal = 252;									//Count and packet data received but checksum error
					}
				}
			}
		}
		//FC_CAL_Bit_High(%a_MX_RF_FSEL_PORT, %a_MX_RF_FSEL_PIN);		// FSEL Output 1

		//SPI_Command(PMCREG);
		//SPI_Command(GENCREG);
		//SPI_Command(GENCREG | 0x0040);
		//SPI_Command(PMCREG | 0x0080);

		SPI_Command(FIFORSTREG);
		SPI_Command(FIFORSTREG | MX_RF_EXTID | 0x0002);		// reset FIFO
	}

	FC_CAL_Bit_High(%a_MX_RF_FSEL_PORT, %a_MX_RF_FSEL_PIN);		// FSEL Output 1
	FC_CAL_Bit_High(%a_MX_RF_CS_PORT, %a_MX_RF_CS_PIN);			// Chip select high, end transmission

	return (retVal);

/*Macro_Check_Buffer_End*/
}

MX_UINT8 Get_Data_Count (void)
{
/*Macro_Get_Data_Count_Start*/

	return(MX_RF_RX_Buffer[0]);

/*Macro_Get_Data_Count_End*/
}

MX_UINT8 Get_Buffer_Data (MX_UINT8 Index)
{
/*Macro_Get_Buffer_Data_Start*/

	if (Index < MX_RF_BUFFER_MAX)
		return(MX_RF_RX_Buffer[Index + 1]);
	else
		return(0);

/*Macro_Get_Buffer_Data_End*/
}




