/*********************************************************************
 *                  Flowcode CAL SPI File
 *
 * File: PIC16BIT_CAL_SPI.c
 *
 * (c) 2011 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
 * -------+----+-----------------------------------------------------
 * 090911 | BR | Created
 * 050312 | BR | Updated to v5.1 CAL Schema
 * 200712 | BR | Added new macro to configure prescaler on the fly
 */


//Remappable Defines
#ifdef MX_SPI_1_FREEALLOC
  #ifdef MX_SPI1_ALT
	#undef MX_SPI_1_MOSI_PIN
	#undef MX_SPI_1_MOSI_PORT
	#undef MX_SPI_1_MOSI_TRIS
	#undef MX_SPI_1_MISO_PIN
	#undef MX_SPI_1_MISO_PORT
	#undef MX_SPI_1_MISO_TRIS
	#undef MX_SPI_1_CLK_PIN
	#undef MX_SPI_1_CLK_PORT
	#undef MX_SPI_1_CLK_TRIS
	#undef MX_SPI_1_SS_PIN
	#undef MX_SPI_1_SS_PORT
	#undef MX_SPI_1_SS_TRIS
	#define MX_SPI_1_MOSI_PIN		15
	#define MX_SPI_1_MOSI_PORT		portb
	#define MX_SPI_1_MOSI_TRIS		trisb
	#define MX_SPI_1_MISO_PIN		14
	#define MX_SPI_1_MISO_PORT		portb
	#define MX_SPI_1_MISO_TRIS		trisb
	#define MX_SPI_1_CLK_PIN		9
	#define MX_SPI_1_CLK_PORT		portb
	#define MX_SPI_1_CLK_TRIS		trisb
	#define MX_SPI_1_SS_PIN			10
	#define MX_SPI_1_SS_PORT		portb
	#define MX_SPI_1_SS_TRIS		trisb
  #else
	#undef MX_SPI_1_MOSI_PIN
	#undef MX_SPI_1_MOSI_PORT
	#undef MX_SPI_1_MOSI_TRIS
	#undef MX_SPI_1_MISO_PIN
	#undef MX_SPI_1_MISO_PORT
	#undef MX_SPI_1_MISO_TRIS
	#undef MX_SPI_1_CLK_PIN
	#undef MX_SPI_1_CLK_PORT
	#undef MX_SPI_1_CLK_TRIS
	#undef MX_SPI_1_SS_PIN
	#undef MX_SPI_1_SS_PORT
	#undef MX_SPI_1_SS_TRIS
	#define MX_SPI_1_MOSI_PIN		5
	#define MX_SPI_1_MOSI_PORT		portb
	#define MX_SPI_1_MOSI_TRIS		trisb
	#define MX_SPI_1_MISO_PIN		4
	#define MX_SPI_1_MISO_PORT		portb
	#define MX_SPI_1_MISO_TRIS		trisb
	#define MX_SPI_1_CLK_PIN		3
	#define MX_SPI_1_CLK_PORT		portb
	#define MX_SPI_1_CLK_TRIS		trisb
	#define MX_SPI_1_SS_PIN			10
	#define MX_SPI_1_SS_PORT		portb
	#define MX_SPI_1_SS_TRIS		trisb
  #endif
#endif
#ifdef MX_SPI1_PORT_E16ALLOC
	#undef MX_SPI_1_MOSI_PIN
	#undef MX_SPI_1_MOSI_PORT
	#undef MX_SPI_1_MOSI_TRIS
	#undef MX_SPI_1_MISO_PIN
	#undef MX_SPI_1_MISO_PORT
	#undef MX_SPI_1_MISO_TRIS
	#undef MX_SPI_1_CLK_PIN
	#undef MX_SPI_1_CLK_PORT
	#undef MX_SPI_1_CLK_TRIS
	#undef MX_SPI_1_SS_PIN
	#undef MX_SPI_1_SS_PORT
	#undef MX_SPI_1_SS_TRIS
	#define MX_SPI_1_MOSI_PIN		0
	#define MX_SPI_1_MOSI_PORT		portc
	#define MX_SPI_1_MOSI_TRIS		trisc
	#define MX_SPI_1_MISO_PIN		1
	#define MX_SPI_1_MISO_PORT		portc
	#define MX_SPI_1_MISO_TRIS		trisc
	#define MX_SPI_1_CLK_PIN		15
	#define MX_SPI_1_CLK_PORT		portb
	#define MX_SPI_1_CLK_TRIS		trisb
	#define MX_SPI_1_SS_PIN			10
	#define MX_SPI_1_SS_PORT		portb
	#define MX_SPI_1_SS_TRIS		trisb
#endif
#ifdef MX_SPI_2_FREEALLOC
	#undef MX_SPI_2_MOSI_PIN
	#undef MX_SPI_2_MOSI_PORT
	#undef MX_SPI_2_MOSI_TRIS
	#undef MX_SPI_2_MISO_PIN
	#undef MX_SPI_2_MISO_PORT
	#undef MX_SPI_2_MISO_TRIS
	#undef MX_SPI_2_CLK_PIN
	#undef MX_SPI_2_CLK_PORT
	#undef MX_SPI_2_CLK_TRIS
	#undef MX_SPI_2_SS_PIN
	#undef MX_SPI_2_SS_PORT
	#undef MX_SPI_2_SS_TRIS
	#define MX_SPI_2_MOSI_PIN		15
	#define MX_SPI_2_MOSI_PORT		portb
	#define MX_SPI_2_MOSI_TRIS		trisb
	#define MX_SPI_2_MISO_PIN		14
	#define MX_SPI_2_MISO_PORT		portb
	#define MX_SPI_2_MISO_TRIS		trisb
	#define MX_SPI_2_CLK_PIN		13
	#define MX_SPI_2_CLK_PORT		portb
	#define MX_SPI_2_CLK_TRIS		trisb
	#define MX_SPI_2_SS_PIN			10
	#define MX_SPI_2_SS_PORT		portb
	#define MX_SPI_2_SS_TRIS		trisb
#endif
#ifdef MX_SPI_2_PORT_E16ALLOC
	#undef MX_SPI_2_MOSI_PIN
	#undef MX_SPI_2_MOSI_PORT
	#undef MX_SPI_2_MOSI_TRIS
	#undef MX_SPI_2_MISO_PIN
	#undef MX_SPI_2_MISO_PORT
	#undef MX_SPI_2_MISO_TRIS
	#undef MX_SPI_2_CLK_PIN
	#undef MX_SPI_2_CLK_PORT
	#undef MX_SPI_2_CLK_TRIS
	#undef MX_SPI_2_SS_PIN
	#undef MX_SPI_2_SS_PORT
	#undef MX_SPI_2_SS_TRIS
	#define MX_SPI_1_MOSI_PIN		5
	#define MX_SPI_1_MOSI_PORT		portc
	#define MX_SPI_2_MOSI_TRIS		trisc
	#define MX_SPI_1_MISO_PIN		4
	#define MX_SPI_1_MISO_PORT		portc
	#define MX_SPI_2_MISO_TRIS		trisc
	#define MX_SPI_1_CLK_PIN		8
	#define MX_SPI_1_CLK_PORT		portc
	#define MX_SPI_2_CLK_TRIS		trisc
	#define MX_SPI_1_SS_PIN			10
	#define MX_SPI_1_SS_PORT		portb
	#define MX_SPI_2_SS_TRIS		trisb
#endif
#ifdef MX_SPI_3_FREEALLOC
	#undef MX_SPI_3_MOSI_PIN
	#undef MX_SPI_3_MOSI_PORT
	#undef MX_SPI_3_MOSI_TRIS
	#undef MX_SPI_3_MISO_PIN
	#undef MX_SPI_3_MISO_PORT
	#undef MX_SPI_3_MISO_TRIS
	#undef MX_SPI_3_CLK_PIN
	#undef MX_SPI_3_CLK_PORT
	#undef MX_SPI_3_CLK_TRIS
	#undef MX_SPI_3_SS_PIN
	#undef MX_SPI_3_SS_PORT
	#undef MX_SPI_3_SS_TRIS
	#define MX_SPI_3_MOSI_PIN		3
	#define MX_SPI_3_MOSI_PORT		portd
	#define MX_SPI_3_MOSI_TRIS		trisd
	#define MX_SPI_3_MISO_PIN		4
	#define MX_SPI_3_MISO_PORT		portd
	#define MX_SPI_3_MISO_TRIS		trisd
	#define MX_SPI_3_CLK_PIN		5
	#define MX_SPI_3_CLK_PORT		portd
	#define MX_SPI_3_CLK_TRIS		trisd
	#define MX_SPI_3_SS_PIN			10
	#define MX_SPI_3_SS_PORT		portb
	#define MX_SPI_3_SS_TRIS		trisb
#endif


//When using hardware SPI channels override port and pin conns with FCD conn definitions
//Only overwrite CS pin defines when using SPI in slave mode on a hardware channel
//Also sort out postscale and prescale options for hardware channels

#define MX_SPI_REF_X			CAL_APPEND(MX_SPI_REF, MX_SPI_NUM)
#define MX_SPI_CHANNEL_X		CAL_APPEND(MX_SPI_CHANNEL_, MX_SPI_NUM)
#define MX_SPI_MOSI_PIN_X		CAL_APPEND(MX_SPI_MOSI_PIN_, MX_SPI_NUM)
#define MX_SPI_MOSI_PORT_X		CAL_APPEND(MX_SPI_MOSI_PORT_, MX_SPI_NUM)
#define MX_SPI_MOSI_TRIS_X		CAL_APPEND(MX_SPI_MOSI_TRIS_, MX_SPI_NUM)
#define MX_SPI_MISO_PIN_X		CAL_APPEND(MX_SPI_MISO_PIN_, MX_SPI_NUM)
#define MX_SPI_MISO_PORT_X		CAL_APPEND(MX_SPI_MISO_PORT_, MX_SPI_NUM)
#define MX_SPI_MISO_TRIS_X		CAL_APPEND(MX_SPI_MISO_TRIS_, MX_SPI_NUM)
#define MX_SPI_SCK_PIN_X		CAL_APPEND(MX_SPI_SCK_PIN_, MX_SPI_NUM)
#define MX_SPI_SCK_PORT_X		CAL_APPEND(MX_SPI_SCK_PORT_, MX_SPI_NUM)
#define MX_SPI_SCK_TRIS_X		CAL_APPEND(MX_SPI_SCK_TRIS_, MX_SPI_NUM)
#define MX_SPI_CS_PIN_X			CAL_APPEND(MX_SPI_CS_PIN_, MX_SPI_NUM)
#define MX_SPI_CS_PORT_X		CAL_APPEND(MX_SPI_CS_PORT_, MX_SPI_NUM)
#define MX_SPI_CS_TRIS_X		CAL_APPEND(MX_SPI_CS_TRIS_, MX_SPI_NUM)
#define MX_SPI_BMODE_X			CAL_APPEND(MX_SPI_BMODE_, MX_SPI_NUM)
#define MX_SPI_PR_SCALE_X		CAL_APPEND(MX_SPI_PR_SCALE_, MX_SPI_NUM)
#define MX_SPI_PO_SCALE_X		CAL_APPEND(MX_SPI_PO_SCALE_, MX_SPI_NUM)
#define MX_SPI_INT_X			CAL_APPEND(MX_SPI_INT_, MX_SPI_NUM)

#define MX_PRESCALE_VAR_X		CAL_APPEND(prescale_, MX_SPI_NUM)

//Setup Definitions
#ifdef MX_SPI_REF_X
	#if MX_SPI_CHANNEL_X > 0
		#undef MX_SPI_MOSI_PIN_X
		#undef MX_SPI_MOSI_PORT_X
		#undef MX_SPI_MOSI_TRIS_X
		#undef MX_SPI_MISO_PIN_X
		#undef MX_SPI_MISO_PORT_X
		#undef MX_SPI_MISO_TRIS_X
		#undef MX_SPI_SCK_PIN_X
		#undef MX_SPI_SCK_PORT_X
		#undef MX_SPI_SCK_TRIS_X
		#undef MX_SPI_CS_PIN_X
		#undef MX_SPI_CS_PORT_X
		#undef MX_SPI_CS_TRIS_X

		#if MX_SPI_PR_SCALE_X == 2
			#undef MX_SPI_PR_SCALE_X
			#define MX_SPI_PR_SCALE_X	0x1B
		#endif
		#if MX_SPI_PR_SCALE_X == 4
			#undef MX_SPI_PR_SCALE_X
			#define MX_SPI_PR_SCALE_X	0x1E
		#endif
		#if MX_SPI_PR_SCALE_X == 8
			#undef MX_SPI_PR_SCALE_X
			#define MX_SPI_PR_SCALE_X	0x1A
		#endif
		#if MX_SPI_PR_SCALE_X == 16
			#undef MX_SPI_PR_SCALE_X
			#define MX_SPI_PR_SCALE_X	0x1D
		#endif
		#if MX_SPI_PR_SCALE_X == 32
			#undef MX_SPI_PR_SCALE_X
			#define MX_SPI_PR_SCALE_X	0x19
		#endif
		#if MX_SPI_PR_SCALE_X == 64
			#undef MX_SPI_PR_SCALE_X
			#define MX_SPI_PR_SCALE_X	0x1C
		#endif
		#if MX_SPI_PR_SCALE_X == 128
			#undef MX_SPI_PR_SCALE_X
			#define MX_SPI_PR_SCALE_X	0x18
		#endif
		#if MX_SPI_PR_SCALE_X == 192
			#undef MX_SPI_PR_SCALE_X
			#define MX_SPI_PR_SCALE_X	0x14
		#endif
	#endif
	#if MX_SPI_CHANNEL_X == 1
		#define MX_SPI_MOSI_PIN_X		MX_SPI_1_MOSI_PIN
		#define MX_SPI_MOSI_PORT_X		MX_SPI_1_MOSI_PORT
		#define MX_SPI_MOSI_TRIS_X		MX_SPI_1_MOSI_TRIS
		#define MX_SPI_MISO_PIN_X		MX_SPI_1_MISO_PIN
		#define MX_SPI_MISO_PORT_X		MX_SPI_1_MISO_PORT
		#define MX_SPI_MISO_TRIS_X		MX_SPI_1_MISO_TRIS
		#define MX_SPI_SCK_PIN_X		MX_SPI_1_CLK_PIN
		#define MX_SPI_SCK_PORT_X		MX_SPI_1_CLK_PORT
		#define MX_SPI_SCK_TRIS_X		MX_SPI_1_CLK_TRIS
		#define MX_SPI_CS_PIN_X			MX_SPI_1_SS_PIN
		#define MX_SPI_CS_PORT_X		MX_SPI_1_SS_PORT
		#define MX_SPI_CS_TRIS_X		MX_SPI_1_SS_TRIS
	#endif
	#if MX_SPI_CHANNEL_X == 2
		#define MX_SPI_MOSI_PIN_X		MX_SPI_2_MOSI_PIN
		#define MX_SPI_MOSI_PORT_X		MX_SPI_2_MOSI_PORT
		#define MX_SPI_MOSI_TRIS_X		MX_SPI_2_MOSI_TRIS
		#define MX_SPI_MISO_PIN_X		MX_SPI_2_MISO_PIN
		#define MX_SPI_MISO_PORT_X		MX_SPI_2_MISO_PORT
		#define MX_SPI_MISO_TRIS_X		MX_SPI_2_MISO_TRIS
		#define MX_SPI_SCK_PIN_X		MX_SPI_2_CLK_PIN
		#define MX_SPI_SCK_PORT_X		MX_SPI_2_CLK_PORT
		#define MX_SPI_SCK_TRIS_X		MX_SPI_2_CLK_TRIS
		#define MX_SPI_CS_PIN_X			MX_SPI_2_SS_PIN
		#define MX_SPI_CS_PORT_X		MX_SPI_2_SS_PORT
		#define MX_SPI_CS_TRIS_X		MX_SPI_2_SS_TRIS
	#endif
	#if MX_SPI_CHANNEL_X == 3
		#define MX_SPI_MOSI_PIN_X		MX_SPI_3_MOSI_PIN
		#define MX_SPI_MOSI_PORT_X		MX_SPI_3_MOSI_PORT
		#define MX_SPI_MOSI_TRIS_X		MX_SPI_3_MOSI_TRIS
		#define MX_SPI_MISO_PIN_X		MX_SPI_3_MISO_PIN
		#define MX_SPI_MISO_PORT_X		MX_SPI_3_MISO_PORT
		#define MX_SPI_MISO_TRIS_X		MX_SPI_3_MISO_TRIS
		#define MX_SPI_SCK_PIN_X		MX_SPI_3_CLK_PIN
		#define MX_SPI_SCK_PORT_X		MX_SPI_3_CLK_PORT
		#define MX_SPI_SCK_TRIS_X		MX_SPI_3_CLK_TRIS
		#define MX_SPI_CS_PIN_X			MX_SPI_3_SS_PIN
		#define MX_SPI_CS_PORT_X		MX_SPI_3_SS_PORT
		#define MX_SPI_CS_TRIS_X		MX_SPI_3_SS_TRIS
	#endif
	#if MX_SPI_CHANNEL_X == 4
		#define MX_SPI_MOSI_PIN_X		MX_SPI_4_MOSI_PIN
		#define MX_SPI_MOSI_PORT_X		MX_SPI_4_MOSI_PORT
		#define MX_SPI_MOSI_TRIS_X		MX_SPI_4_MOSI_TRIS
		#define MX_SPI_MISO_PIN_X		MX_SPI_4_MISO_PIN
		#define MX_SPI_MISO_PORT_X		MX_SPI_4_MISO_PORT
		#define MX_SPI_MISO_TRIS_X		MX_SPI_4_MISO_TRIS
		#define MX_SPI_SCK_PIN_X		MX_SPI_4_CLK_PIN
		#define MX_SPI_SCK_PORT_X		MX_SPI_4_CLK_PORT
		#define MX_SPI_SCK_TRIS_X		MX_SPI_4_CLK_TRIS
		#define MX_SPI_CS_PIN_X			MX_SPI_4_SS_PIN
		#define MX_SPI_CS_PORT_X		MX_SPI_4_SS_PORT
		#define MX_SPI_CS_TRIS_X		MX_SPI_4_SS_TRIS
	#endif
#else
	#error "SPI CAL reference not defined!"
#endif


MX_UINT8 MX_PRESCALE_VAR_X = MX_SPI_PR_SCALE_X;


//Function Prototypes
CALFUNCTION(void, FC_CAL_SPI_Master_Init_, (void));
CALFUNCTION(void, FC_CAL_SPI_Master_Uninit_, (void));
CALFUNCTION(MX_UINT8, FC_CAL_SPI_Master_Byte_, (MX_UINT8 DataOut));
CALFUNCTION(void, FC_CAL_SPI_Set_Prescaler_, (MX_UINT8 Prescaler));

CALFUNCTION(void, FC_CAL_SPI_Slave_Init_, (void));
CALFUNCTION(void, FC_CAL_SPI_Slave_Uninit_, (void));
CALFUNCTION(void, FC_CAL_SPI_Slave_SetTxData_, (MX_UINT8 Data));
CALFUNCTION(MX_UINT8, FC_CAL_SPI_Slave_GetRxData_, (void));


#ifndef SPI1CON1
	#define SPI1CON1		SPI1CON
	#define SPI1CON1bits	SPI1CONbits
#endif



//Bus Mode - Bit0=CPOL, Bit1=CPHA, Bit2=CSMP
//CPOL - Clock Polarity - Idle State of the clock 0=0, 1=1
//CPHA - Clock Phase - Clock Edge 0=leading edge, 1=trailing edge
//CSMP - Input Data Bit Sample Phase
//CRAT - SPI Clock Rate 0=1/4, 1=1/16, 2=1/64



CALFUNCTION(void, FC_CAL_SPI_Master_Init_, (void))
{
	FC_CAL_Bit_High_DDR (MX_SPI_MOSI_PORT_X, MX_SPI_MOSI_TRIS_X, MX_SPI_MOSI_PIN_X);		// MOSI pin is default high
	FC_CAL_Bit_In_DDR   (MX_SPI_MISO_PORT_X, MX_SPI_MISO_TRIS_X, MX_SPI_MISO_PIN_X);		// MISO pin is a input

	#if (MX_SPI_BMODE_X & 0x02)
		FC_CAL_Bit_Low_DDR  (MX_SPI_SCK_PORT_X, MX_SPI_SCK_TRIS_X, MX_SPI_SCK_PIN_X);		// Clock pin is default low
	#else
		FC_CAL_Bit_High_DDR (MX_SPI_SCK_PORT_X, MX_SPI_SCK_TRIS_X, MX_SPI_SCK_PIN_X);		// Clock pin is default high
	#endif

	#if (MX_SPI_CHANNEL_X == 1)
	 #ifndef MX_SPI_1
	 	#error "SPI channel 1 not available on this device"
	 #else
	  #ifdef MX_SPI_1_FREEALLOC
	   #ifdef MX_SPI1_ALT
		RPINR20 = (RPINR20 & 0xFF00) | 0x0E;					//Assign SDI - RP14 / PORTB14
		RPOR4 = (RPOR4 & 0x00FF) | 0x0800;						//Assign SCK - RP9  / PORTB9
		RPOR7 = (RPOR7 & 0x00FF) | 0x0700;						//Assign SDO - RP15 / PORTB15
	   #else
		RPINR20 = (RPINR20 & 0xFF00) | 0x04;					//Assign SDI - RP4 / PORTB4
		RPOR1 = (RPOR1 & 0x00FF) | 0x0800;						//Assign SCK - RP3 / PORTB3
		RPOR2 = (RPOR2 & 0x00FF) | 0x0700;						//Assign SDO - RP5 / PORTB5
	   #endif
	  #endif
	  #ifdef MX_SPI1_PORT_E16ALLOC
		RPINR20 = (RPINR20 & 0xFF00) | 0x11;					//Assign SDI - RP17 / PORTC1
		RPOR7 = (RPOR7 & 0x00FF) | 0x0800;						//Assign SCK - RP15 / PORTB15
		RPOR8 = (RPOR8 & 0xFF00) | 0x0007;						//Assign SDO - RP16 / PORTC0
	  #endif

		SPI1CON1 = MX_PRESCALE_VAR_X & 0x1F;					//Assign Clock Prescalers
		SPI1CON1bits.CKP = MX_SPI_BMODE_X & 0x01;				//Assign Clock Polarity
		SPI1CON1bits.CKE = (MX_SPI_BMODE_X & 0x02) >> 1;		//Assign Clock Phase
		SPI1CON1bits.SMP = (MX_SPI_BMODE_X & 0x04) >> 2;		//Assign Input Data Phase
		SPI1CON1bits.MSTEN = 1;									//master mode
		SPI1STATbits.SPIROV = 0;								//clear unread data flag
		SPI1STATbits.SPIEN = 1;									//enable SPI peripheral
	 #endif
	#endif

	#if (MX_SPI_CHANNEL_X == 2)
	 #ifndef MX_SPI_2
	 	#error "SPI channel 2 not available on this device"
	 #else
	  #ifdef MX_SPI_2_FREEALLOC
		RPINR22 = (RPINR22 & 0xFF00) | 0x0E;					//Assign SDI - RP14 / PORTB14
		RPOR6 = (RPOR6 & 0x00FF) | 0x0B00;						//Assign SCK - RP13 / PORTB13
		RPOR7 = (RPOR7 & 0x00FF) | 0x0A00;						//Assign SDO - RP15 / PORTB15
	  #endif
	  #ifdef MX_SPI2_PORT_E16ALLOC
		RPINR22 = (RPINR22 & 0xFF00) | 0x14;					//Assign SDI - RP20 / PORTC4
		RPOR12 = (RPOR12 & 0xFF00) | 0x000B;					//Assign SCK - RP24 / PORTC8
		RPOR10 = (RPOR10 & 0x00FF) | 0x0A00;					//Assign SDO - RP21 / PORTC5
	  #endif

		SPI2CON1 = MX_PRESCALE_VAR_X & 0x1F;					//Assign Clock Prescalers
		SPI2CON1bits.CKP = MX_SPI_BMODE_X & 0x01;				//Assign Clock Polarity
		SPI2CON1bits.CKE = (MX_SPI_BMODE_X & 0x02) >> 1;		//Assign Clock Phase
		SPI2CON1bits.SMP = (MX_SPI_BMODE_X & 0x04) >> 2;		//Assign Input Data Phase
		SPI2CON1bits.MSTEN = 1;									//master mode
		SPI2STATbits.SPIROV = 0;								//clear unread data flag
		SPI2STATbits.SPIEN = 1;									//enable SPI peripheral
	 #endif
	#endif

	#if (MX_SPI_CHANNEL_X == 3)
	 #ifndef MX_SPI_3
	 	#error "SPI channel 3 not available on this device"
	 #else
	  #ifdef MX_SPI_3_FREEALLOC
		RPINR28 = (RPINR28 & 0xFF00) | 0x19;					//Assign SDI - RP25 / PORTD4
		RPOR11 = (RPOR11 & 0xFF00) | 0x21;						//Assign SCK - RP22 / PORTD5
		RPOR10 = (RPOR10 & 0xFF00) | 0x20;						//Assign SDO - RP20 / PORTD3
	  #endif

		SPI3CON1 = MX_PRESCALE_VAR_X & 0x1F;					//Assign Clock Prescalers
		SPI3CON1bits.CKP = MX_SPI_BMODE_X & 0x01;				//Assign Clock Polarity
		SPI3CON1bits.CKE = (MX_SPI_BMODE_X & 0x02) >> 1;		//Assign Clock Phase
		SPI3CON1bits.SMP = (MX_SPI_BMODE_X & 0x04) >> 2;		//Assign Input Data Phase
		SPI3CON1bits.MSTEN = 1;									//master mode
		SPI3STATbits.SPIROV = 0;								//clear unread data flag
		SPI3STATbits.SPIEN = 1;									//enable SPI peripheral
	 #endif
	#endif

	#if (MX_SPI_CHANNEL_X == 4)
	 #ifndef MX_SPI_4
	 	#error "SPI channel 4 not available on this device"
	 #else
		SPI4CON1 = MX_PRESCALE_VAR_X & 0x1F;					//Assign Clock Prescalers
		SPI4CON1bits.CKP = MX_SPI_BMODE_X & 0x01;				//Assign Clock Polarity
		SPI4CON1bits.CKE = (MX_SPI_BMODE_X & 0x02) >> 1;		//Assign Clock Phase
		SPI4CON1bits.SMP = (MX_SPI_BMODE_X & 0x04) >> 2;		//Assign Input Data Phase
		SPI4CON1bits.MSTEN = 1;									//master mode
		SPI4STATbits.SPIROV = 0;								//clear unread data flag
		SPI4STATbits.SPIEN = 1;									//enable SPI peripheral
	 #endif
	#endif
}


CALFUNCTION(void, FC_CAL_SPI_Master_Uninit_, (void))
{
	#if (MX_SPI_CHANNEL_X == 1)
		SPI1STATbits.SPIEN = 0;		//disable SPI peripheral
	#endif

	#if (MX_SPI_CHANNEL_X == 2)
		SPI2STATbits.SPIEN = 0;		//disable SPI peripheral
	#endif

	#if (MX_SPI_CHANNEL_X == 3)
		SPI3STATbits.SPIEN = 0;		//disable SPI peripheral
	#endif

	#if (MX_SPI_CHANNEL_X == 4)
		SPI4STATbits.SPIEN = 0;		//disable SPI peripheral
	#endif

	//Reset Pins to Inputs
	FC_CAL_Bit_In_DDR (MX_SPI_MOSI_PORT_X, MX_SPI_MOSI_TRIS_X, MX_SPI_MOSI_PIN_X);
	FC_CAL_Bit_In_DDR (MX_SPI_MISO_PORT_X, MX_SPI_MISO_TRIS_X, MX_SPI_MISO_PIN_X);
	FC_CAL_Bit_In_DDR (MX_SPI_SCK_PORT_X, MX_SPI_SCK_TRIS_X, MX_SPI_SCK_PIN_X);
}


CALFUNCTION(MX_UINT8, FC_CAL_SPI_Master_Byte_, (MX_UINT8 DataOut))
{
	MX_UINT8 retVal = 0;

	#if (MX_SPI_CHANNEL_X == 0)

		MX_UINT8 i, idx;
		for (idx = 0; idx < 8; idx++)
		{
			retVal = retVal << 1;

			#if ((MX_SPI_BMODE_X & 0x02) == 0x00)									//CKE = 0; Set SCK active before data
				#if ((MX_SPI_BMODE_X & 0x01) == 0x00)								//CKP = 0
					FC_CAL_Bit_High(MX_SPI_SCK_PORT_X, MX_SPI_SCK_PIN_X);
				#else
					FC_CAL_Bit_Low(MX_SPI_SCK_PORT_X, MX_SPI_SCK_PIN_X);
				#endif
			#endif

			if (DataOut & 0x80)														//Test Data bit
				FC_CAL_Bit_High(MX_SPI_MOSI_PORT_X, MX_SPI_MOSI_PIN_X);			//Set SDO bit
			else
				FC_CAL_Bit_Low (MX_SPI_MOSI_PORT_X, MX_SPI_MOSI_PIN_X);			//Clear SDO bit

			for (i=0; i<MX_PRESCALE_VAR_X; i++)
				nop();

			#if ((MX_SPI_BMODE_X & 0x02) == 0x02)									//CKE = 1; Set SCK active after data
				#if ((MX_SPI_BMODE_X & 0x01) == 0x00)								//CKP = 0
					FC_CAL_Bit_High(MX_SPI_SCK_PORT_X, MX_SPI_SCK_PIN_X);
				#else
					FC_CAL_Bit_Low(MX_SPI_SCK_PORT_X, MX_SPI_SCK_PIN_X);
				#endif
			#else																	//CKE = 0; Set SCK idle after data
				#if ((MX_SPI_BMODE_X & 0x01) == 0x00)								//CKP = 0
					FC_CAL_Bit_Low(MX_SPI_SCK_PORT_X, MX_SPI_SCK_PIN_X);
				#else
					FC_CAL_Bit_High(MX_SPI_SCK_PORT_X, MX_SPI_SCK_PIN_X);
				#endif
			#endif

			#if ((MX_SPI_BMODE_X & 0x04) == 0)										//Sample at the middle of period
				if(FC_CAL_Bit_In(MX_SPI_MISO_PORT_X, MX_SPI_MISO_PIN_X))
					retVal = retVal | 0x01;
				else
					retVal = retVal & 0xFE;
			#endif

			for (i=0; i<MX_PRESCALE_VAR_X; i++)
				nop();

			#if ((MX_SPI_BMODE_X & 0x02) == 0x02)									//CKE = 1; Set SCK idle to complete cycle																	//CKE = 0; Set SCK idle after data
				#if ((MX_SPI_BMODE_X & 0x01) == 0x00)								//CKP = 0
					FC_CAL_Bit_Low(MX_SPI_SCK_PORT_X, MX_SPI_SCK_PIN_X);
				#else
					FC_CAL_Bit_High(MX_SPI_SCK_PORT_X, MX_SPI_SCK_PIN_X);
				#endif
			#endif

			#if ((MX_SPI_BMODE_X & 0x04) == 0x04)									//Sample at the end of period
				if(FC_CAL_Bit_In(MX_SPI_MISO_PORT_X, MX_SPI_MISO_PIN_X))
					retVal = retVal | 0x01;
				else
					retVal = retVal & 0xFE;
			#endif

			DataOut = DataOut << 1;							//Move to next data bit
		}
    #endif

	#if (MX_SPI_CHANNEL_X == 1)
		SPI1BUF = DataOut;						//send outgoing byte
		while (SPI1STATbits.SPIRBF == 0);		//wait until data has been sent
		retVal = SPI1BUF;						//receive the byte
	#endif

	#if (MX_SPI_CHANNEL_X == 2)
		SPI2BUF = DataOut;						//send outgoing byte
		while (SPI2STATbits.SPIRBF == 0);		//wait until data has been sent
		retVal = SPI2BUF;						//receive the byte
	#endif

	#if (MX_SPI_CHANNEL_X == 3)
		SPI3BUF = DataOut;						//send outgoing byte
		while (SPI3STATbits.SPIRBF == 0);		//wait until data has been sent
		retVal = SPI3BUF;						//receive the byte
	#endif

	#if (MX_SPI_CHANNEL_X == 4)
		SPI4BUF = DataOut;						//send outgoing byte
		while (SPI4STATbits.SPIRBF == 0);		//wait until data has been sent
		retVal = SPI4BUF;						//receive the byte
	#endif

	return (retVal);
}


CALFUNCTION(void, FC_CAL_SPI_Set_Prescaler_, (MX_UINT8 Prescaler))
{
	MX_PRESCALE_VAR_X = Prescaler;

	#if (MX_SPI_CHANNEL_X > 0)
		if (Prescaler == 2)
			MX_PRESCALE_VAR_X = 0x1B;
		if (Prescaler == 4)
			MX_PRESCALE_VAR_X = 0x1E;
		if (Prescaler == 8)
			MX_PRESCALE_VAR_X = 0x1A;
		if (Prescaler == 16)
			MX_PRESCALE_VAR_X = 0x1D;
		if (Prescaler == 32)
			MX_PRESCALE_VAR_X = 0x19;
		if (Prescaler == 64)
			MX_PRESCALE_VAR_X = 0x1C;
		if (Prescaler == 128)
			MX_PRESCALE_VAR_X = 0x18;
		if (Prescaler == 192)
			MX_PRESCALE_VAR_X = 0x14;
	#endif

	#if (MX_SPI_CHANNEL_X == 1)
		SPI1STATbits.SPIEN = 0;									//Disable SPI peripheral
		SPI1CON1 = MX_PRESCALE_VAR_X & 0x1F;					//Assign Clock Prescalers
		SPI1STATbits.SPIEN = 1;									//Enable SPI peripheral
	 #endif
	#endif

	#if (MX_SPI_CHANNEL_X == 2)
		SPI2STATbits.SPIEN = 0;									//Disable SPI peripheral
		SPI2CON1 = MX_PRESCALE_VAR_X & 0x1F;					//Assign Clock Prescalers
		SPI2STATbits.SPIEN = 1;									//Enable SPI peripheral
	 #endif
	#endif

	#if (MX_SPI_CHANNEL_X == 3)
		SPI3STATbits.SPIEN = 0;									//Disable SPI peripheral
		SPI3CON1 = MX_PRESCALE_VAR_X & 0x1F;					//Assign Clock Prescalers
		SPI3STATbits.SPIEN = 1;									//Enable SPI peripheral
	 #endif
	#endif

	#if (MX_SPI_CHANNEL_X == 4)
		SPI4STATbits.SPIEN = 0;									//Disable SPI peripheral
		SPI4CON1 = MX_PRESCALE_VAR_X & 0x1F;					//Assign Clock Prescalers
		SPI4STATbits.SPIEN = 1;									//Enable SPI peripheral
	 #endif
	#endif
}




CALFUNCTION(void, FC_CAL_SPI_Slave_Init_, (void))
{

}

CALFUNCTION(void, FC_CAL_SPI_Slave_Uninit_, (void))
{

}

CALFUNCTION(void, FC_CAL_SPI_Slave_SetTxData_, (MX_UINT8 Data))
{

}

CALFUNCTION(MX_UINT8, FC_CAL_SPI_Slave_GetRxData_, (void))
{

}


