/*********************************************************************
 *                 Flowcode CAN Component Code
 *
 * File: PIC16BIT_CAN.c
 *
 * (c) 2009 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
 * -------+----+-----------------------------------------------------
 * 240407 | ST | Created
 * 190607 | BR | Externalised
 * 090707 | ST | Amended and incorporated with OCX component
 * 021208 | SK | New #defines for MIAC compatibility
 * 180309 | BR | Changed delays to be WDT compatible
 * 240309 | BR | Moved private functions from AddDefines section
 * 300409 | BR | Fixed macro param probs and added defines for MIAC CS & INT
 * 130509 | BR | Added % definitions to DefinesCode section
 * 090909 | BR | Ported to HiTECH Compiler.
 * 131109 | BR | Fixed #pragma error HITECH problem
 * 280110 | BR | Fixed Macro Parameter Error
 * 240310 | BR | Added internal CAN functionality
 * 200810 | BR | Updated to work with PIC16 devices
 * 080910 | BR | Added a fix for the SPI postscaler
 * 240910 | BR | Fix for reg definitions in dsPIC30 devices
 * 291010 | BR | Added internal CAN functionality
 ********************************************************************/

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

 Return & parameter types:
   void
   char
   short
   char*

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

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

[Settings]
CLSID={0ACB1934-EB24-4331-BEF4-BADB2DD32F46}
IsAnalogue=0
MultipleAllowed=0
Description=CAN Flowcode Component

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

[Port]
DesiredPort=0
PortMandatory=0
MX_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

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

[PinMustUsePin]
# boolean

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

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

[MacroNames]
Count=22
1=SPI_Init
2=SPI_SendByte
3=CAN_MaskFromBit
4=CAN_Reset
5=CAN_Write
6=CAN_Read
7=CAN_Config
8=CAN_ReadStatus
9=CAN_ReadRXStatus
10=CAN_BitModify
11=CAN_ReadRX_ID_and_Data
12=Init
13=SendBuffer
14=CheckRx
15=ShowLEDs
16=ReadSwitches
17=GetRxDataCount
18=GetRxData
19=SetTxData
20=SetTxID
21=GetRxIDLo
22=GetRxIDHi

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

[MacroIsPrivate]
1=1
2=1
3=1
4=1
5=1
6=1
7=1
8=1
9=1
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


[MacroParameters_SPI_Init]
Count=0

[MacroParamTypes_SPI_Init]


[MacroParameters_SPI_SendByte]
Count=1
1=byte

[MacroParamTypes_SPI_SendByte]
1=char

[MacroParameters_CAN_MaskFromBit]
Count=1
1=which_bit

[MacroParamTypes_CAN_MaskFromBit]
1=char

[MacroParameters_CAN_Reset]
Count=0

[MacroParamTypes_CAN_Reset]


[MacroParameters_CAN_Write]
Count=2
1=addr
2=data

[MacroParamTypes_CAN_Write]
1=char
2=char

[MacroParameters_CAN_Read]
Count=1
1=addr

[MacroParamTypes_CAN_Read]
1=char


[MacroParameters_CAN_Config]
Count=1
1=cfg

[MacroParamTypes_CAN_Config]
1=char


[MacroParameters_CAN_ReadStatus]
Count=0

[MacroParamTypes_CAN_ReadStatus]


[MacroParameters_CAN_ReadRXStatus]
Count=0

[MacroParamTypes_CAN_ReadRXStatus]


[MacroParameters_CAN_BitModify]
Count=3
1=addr
2=mask
3=data

[MacroParamTypes_CAN_BitModify]
1=char
2=char
3=char

[MacroParameters_CAN_ReadRX_ID_and_Data]
Count=1
1=buffer

[MacroParamTypes_CAN_ReadRX_ID_and_Data]
1=char

[MacroParameters_Init]
Count=0

[MacroParamTypes_Init]


[MacroParameters_SendBuffer]
Count=1
1=buffer

[MacroParamTypes_SendBuffer]
1=char

[MacroParameters_CheckRx]
Count=1
1=buffer

[MacroParamTypes_CheckRx]
1=char

[MacroParameters_ShowLEDs]
Count=2
1=led1
2=led2

[MacroParamTypes_ShowLEDs]
1=char
2=char

[MacroParameters_ReadSwitches]
Count=0

[MacroParamTypes_ReadSwitches]


[MacroParameters_GetRxDataCount]
Count=1
1=buffer

[MacroParamTypes_GetRxDataCount]
1=char

[MacroParameters_GetRxData]
Count=2
1=buffer
2=index

[MacroParamTypes_GetRxData]
1=char
2=char

[MacroParameters_SetTxData]
Count=10
1=buffer
2=data_cnt
3=d0
4=d1
5=d2
6=d3
7=d4
8=d5
9=d6
10=d7

[MacroParamTypes_SetTxData]
1=char
2=char
3=char
4=char
5=char
6=char
7=char
8=char
9=char
10=char

[MacroParameters_SetTxID]
Count=3
1=buffer
2=hi
3=lo

[MacroParamTypes_SetTxID]
1=char
2=char
3=char

[MacroParameters_GetRxIDLo]
Count=1
1=buffer

[MacroParamTypes_GetRxIDLo]
1=char

[MacroParameters_GetRxIDHi]
Count=1
1=buffer

[MacroParamTypes_GetRxIDHi]
1=char


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

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

/*DefinesCode_Start*/

/**** Macro Substitutions ****
%a = Chip Select Pin
%b = Interrupt Pin
%c = Interrupt Pin Mask
%d = Filter 1 Configuration
%e = Filter 2 Configuration
%f = Filter 3 Configuration
%g = Buffer Control
%h = TXRTS Control
%i = Transmit Buffer 0 Messages
%j = Transmit Buffer 1 Messages
%k = Transmit Buffer 2 Messages
%l = Receive Buffer 0 Messages
%m = Receive Buffer 1 Messages
%n = Internal CAN enable
%o = Internal Bit Rate0
%p = Internal Bit Rate1
%q = Internal Bit Rate2
%r = SPI port selection
******************************/

//common defines
#define CAN_CHIPSEL  	%a
#define CAN_INTERRUPT  	%b
#define CAN_INT_MASK  	%c
#define CNF1_VAL  		%d
#define CNF2_VAL  		%e
#define CNF3_VAL  		%f
#define BFPCTRL_VAL    	%g
#define TXRTSCTRL_VAL	%h

#define CAN_MAX_TX_BUF	(3)
#define CAN_MAX_RX_BUF	(2)

//One shot mode, CLKOUT enable, CLKOUT prescaler
#define CANCTRL_VAL		0x80
#define MX_CANSTAT_VAL	0x80

//Extended ID Dummy Values
#define TXB0EID8_VAL	0x00
#define TXB0EID0_VAL	0x00
#define TXB1EID8_VAL	0x00
#define TXB1EID0_VAL	0x00
#define TXB2EID8_VAL	0x00
#define TXB2EID0_VAL	0x00
#define RXF0EID8_VAL	0x00
#define RXF0EID0_VAL	0x00
#define RXF1EID8_VAL	0x00
#define RXF1EID0_VAL	0x00
#define RXF2EID8_VAL	0x00
#define RXF2EID0_VAL	0x00
#define RXF3EID8_VAL	0x00
#define RXF3EID0_VAL	0x00
#define RXF4EID8_VAL	0x00
#define RXF4EID0_VAL	0x00
#define RXF5EID8_VAL	0x00
#define RXF5EID0_VAL	0x00
#define RXM0EID8_VAL	0xFF
#define RXM0EID0_VAL	0xFF
#define RXM1EID8_VAL	0xFF
#define RXM1EID0_VAL	0xFF

//CANCTRL
#define REQOP_CONFIG		0x0400
#define REQOP_LISTEN		0x0300
#define REQOP_LOOPBACK		0x0200
#define REQOP_SLEEP			0x0100
#define REQOP_NORMAL		0x0000


//Transmission messages (TXB0-2):
%i
%j
%k

//Reception (TXB0-1)
%l
%m

#define INTERNAL_CAN_ENABLE	%n

char CAN_MSG_DLC;
char CAN_MSG_DATA[8];
char MsgFlags = 0;

#ifdef CAN_USE_EXID
  char CAN_MSG_ID[4];
#else
  char CAN_MSG_ID[2];
#endif

#if INTERNAL_CAN_ENABLE == 1

	#define USE_INT_CAN
	#define CAN_OP_MODE_BITS 	0xE0

#else

	#define CAN_SPI_PORT	1//%r

	#if (MX_CLK_SPD > 20)
		#define SPISPEED		0x1D		//Fcycle / 16
	#else
		#define SPISPEED		0x1E		//Fcycle / 4
	#endif

	#if (CAN_SPI_PORT == 1)
		#ifndef MX_SPI1
			#error Chip does not have SPI port 1 capability
		#endif

		#ifdef MX_SPI1_PORT_FREEALLOC

			#ifdef MX_SPI1_ALT

				//component defines
				#define MX_CAN_SDI	14
				#define MX_CAN_SDO	15
				#define MX_CAN_SCK	9

				#define MX_CAN_PORT 		PORTB
				#define MX_CAN_TRIS 		TRISB
				#define MX_CAN_SDO_TRIS 	TRISB
				#define MX_CAN_CS_PORT 		PORTB
				#define MX_CAN_CS_TRIS 		TRISB
				#define MX_CAN_INT_PORT 	PORTB
				#define MX_CAN_INT_TRIS 	TRISB

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

				//component defines
				#define MX_CAN_SDI	4
				#define MX_CAN_SDO	5
				#define MX_CAN_SCK	3

				#define MX_CAN_PORT 		PORTB
				#define MX_CAN_TRIS 		TRISB
				#define MX_CAN_SDO_TRIS 	TRISB
				#define MX_CAN_CS_PORT 		PORTB
				#define MX_CAN_CS_TRIS 		TRISB
				#define MX_CAN_INT_PORT 	PORTB
				#define MX_CAN_INT_TRIS 	TRISB

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

		#else
			#ifdef dsPIC30
				#define SPI1CON1		SPI1CON
				#define SPI1CON1bits	SPI1CONbits
			#endif

			#ifdef MX_SPI1_PORT_A
				#define MX_CAN_PORT 		PORTA
				#define MX_CAN_TRIS 		TRISA
				#define MX_CAN_SDO_TRIS 	TRISA
				#define MX_CAN_CS_PORT 		PORTA
				#define MX_CAN_CS_TRIS 		TRISA
				#define MX_CAN_INT_PORT 	PORTA
				#define MX_CAN_INT_TRIS 	TRISA
			#endif
			#ifdef MX_SPI1_PORT_B
				#define MX_CAN_PORT 		PORTB
				#define MX_CAN_TRIS 		TRISB
				#define MX_CAN_SDO_TRIS 	TRISB
				#define MX_CAN_CS_PORT 		PORTB
				#define MX_CAN_CS_TRIS 		TRISB
				#define MX_CAN_INT_PORT 	PORTB
				#define MX_CAN_INT_TRIS 	TRISB
			#endif
			#ifdef MX_SPI1_PORT_C
				#define MX_CAN_PORT 		PORTC
				#define MX_CAN_TRIS 		TRISC
				#define MX_CAN_SDO_TRIS 	TRISC
				#define MX_CAN_CS_PORT 		PORTC
				#define MX_CAN_CS_TRIS 		TRISC
				#define MX_CAN_INT_PORT 	PORTC
				#define MX_CAN_INT_TRIS 	TRISC
			#endif
			#ifdef MX_SPI1_PORT_D
				#define MX_CAN_PORT 		PORTD
				#define MX_CAN_TRIS 		TRISD
				#define MX_CAN_SDO_TRIS 	TRISD
				#define MX_CAN_CS_PORT 		PORTD
				#define MX_CAN_CS_TRIS 		TRISD
				#define MX_CAN_INT_PORT 	PORTD
				#define MX_CAN_INT_TRIS 	TRISD
			#endif
			#ifdef MX_SPI1_PORT_E
				#define MX_CAN_PORT 		PORTE
				#define MX_CAN_TRIS 		TRISE
				#define MX_CAN_SDO_TRIS 	TRISE
				#define MX_CAN_CS_PORT 		PORTE
				#define MX_CAN_CS_TRIS 		TRISE
				#define MX_CAN_INT_PORT 	PORTE
				#define MX_CAN_INT_TRIS 	TRISE
			#endif
			#ifdef MX_SPI1_PORT_F
				#define MX_CAN_PORT 		PORTF
				#define MX_CAN_TRIS 		TRISF
				#define MX_CAN_SDO_TRIS 	TRISF
				#define MX_CAN_CS_PORT 		PORTF
				#define MX_CAN_CS_TRIS 		TRISF
				#define MX_CAN_INT_PORT 	PORTF
				#define MX_CAN_INT_TRIS 	TRISF
			#endif
			#ifdef MX_SPI1_PORT_G
				#define MX_CAN_PORT 		PORTG
				#define MX_CAN_TRIS 		TRISG
				#define MX_CAN_SDO_TRIS 	TRISG
				#define MX_CAN_CS_PORT 		PORTG
				#define MX_CAN_CS_TRIS 		TRISG
				#define MX_CAN_INT_PORT 	PORTG
				#define MX_CAN_INT_TRIS 	TRISG
			#endif
			#define MX_CAN_SDI	MX_SPI1_SDI
			#define MX_CAN_SDO	MX_SPI1_SDO
			#define MX_CAN_SCK	MX_SPI1_SCK
		#endif
	#endif

	#if (CAN_SPI_PORT == 2)
		#ifndef MX_SPI2
			#error Chip does not have SPI port 2 capability
		#endif

		#ifdef MX_SPI2_PORT_FREEALLOC

			//component defines
			#define MX_CAN_SDI	14
			#define MX_CAN_SDO	15
			#define MX_CAN_SCK	13

			#define MX_CAN_PORT 		PORTB
			#define MX_CAN_TRIS 		TRISB
			#define MX_CAN_SDO_TRIS 	TRISB
			#define MX_CAN_CS_PORT 		PORTB
			#define MX_CAN_CS_TRIS 		TRISB
			#define MX_CAN_INT_PORT 	PORTB
			#define MX_CAN_INT_TRIS 	TRISB

			//configure remapping
			RPINR22 = (RPINR22 & 0xFF00) | 0x0E;	//Assign SDI - RP14 / PORTB14
			RPOR6 = (RPOR6 & 0x00FF) | 0x0B00;		//Assign SCK - RP13 / PORTB13
			RPOR7 = (RPOR7 & 0x00FF) | 0x0A00;		//Assign SDO - RP15 / PORTB15

		#else
			#ifdef dsPIC30
				#define SPI2CON1		SPI2CON
				#define SPI2CON1bits	SPI2CONbits
			#endif

			#ifdef MX_SPI2_PORT_A
				#define MX_CAN_PORT 		PORTA
				#define MX_CAN_TRIS 		TRISA
				#define MX_CAN_SDO_TRIS 	TRISA
				#define MX_CAN_CS_PORT 		PORTA
				#define MX_CAN_CS_TRIS 		TRISA
				#define MX_CAN_INT_PORT 	PORTA
				#define MX_CAN_INT_TRIS 	TRISA
			#endif
			#ifdef MX_SPI2_PORT_B
				#define MX_CAN_PORT 		PORTB
				#define MX_CAN_TRIS 		TRISB
				#define MX_CAN_SDO_TRIS 	TRISB
				#define MX_CAN_CS_PORT 		PORTB
				#define MX_CAN_CS_TRIS 		TRISB
				#define MX_CAN_INT_PORT 	PORTB
				#define MX_CAN_INT_TRIS 	TRISB
			#endif
			#ifdef MX_SPI2_PORT_C
				#define MX_CAN_PORT 		PORTC
				#define MX_CAN_TRIS 		TRISC
				#define MX_CAN_SDO_TRIS 	TRISC
				#define MX_CAN_CS_PORT 		PORTC
				#define MX_CAN_CS_TRIS 		TRISC
				#define MX_CAN_INT_PORT 	PORTC
				#define MX_CAN_INT_TRIS 	TRISC
			#endif
			#ifdef MX_SPI2_PORT_D
				#define MX_CAN_PORT 		PORTD
				#define MX_CAN_TRIS 		TRISD
				#define MX_CAN_SDO_TRIS 	TRISD
				#define MX_CAN_CS_PORT 		PORTD
				#define MX_CAN_CS_TRIS 		TRISD
				#define MX_CAN_INT_PORT 	PORTD
				#define MX_CAN_INT_TRIS 	TRISD
			#endif
			#ifdef MX_SPI2_PORT_E
				#define MX_CAN_PORT 		PORTE
				#define MX_CAN_TRIS 		TRISE
				#define MX_CAN_SDO_TRIS 	TRISE
				#define MX_CAN_CS_PORT 		PORTE
				#define MX_CAN_CS_TRIS 		TRISE
				#define MX_CAN_INT_PORT 	PORTE
				#define MX_CAN_INT_TRIS 	TRISE
			#endif
			#ifdef MX_SPI2_PORT_F
				#define MX_CAN_PORT 		PORTF
				#define MX_CAN_TRIS 		TRISF
				#define MX_CAN_SDO_TRIS 	TRISF
				#define MX_CAN_CS_PORT 		PORTF
				#define MX_CAN_CS_TRIS 		TRISF
				#define MX_CAN_INT_PORT 	PORTF
				#define MX_CAN_INT_TRIS 	TRISF
			#endif
			#ifdef MX_SPI2_PORT_G
				#define MX_CAN_PORT 		PORTG
				#define MX_CAN_TRIS 		TRISG
				#define MX_CAN_SDO_TRIS 	TRISG
				#define MX_CAN_CS_PORT 		PORTG
				#define MX_CAN_CS_TRIS 		TRISG
				#define MX_CAN_INT_PORT 	PORTG
				#define MX_CAN_INT_TRIS 	TRISG
			#endif
			#define MX_CAN_SDI	MX_SPI2_SDI
			#define MX_CAN_SDO	MX_SPI2_SDO
			#define MX_CAN_SCK	MX_SPI2_SCK
		#endif
	#endif

	#if (CAN_SPI_PORT == 3)
		#ifndef MX_SPI3
			#error Chip does not have SPI port 3 capability
		#endif

		#ifdef MX_SPI3_PORT_FREEALLOC

			//component defines
			#define MX_CAN_SDI	4
			#define MX_CAN_SDO	5
			#define MX_CAN_SCK	3

			#define MX_CAN_PORT 		PORTD
			#define MX_CAN_TRIS 		TRISD
			#define MX_CAN_SDO_TRIS 	TRISD
			#define MX_CAN_CS_PORT 		PORTD
			#define MX_CAN_CS_TRIS 		TRISD
			#define MX_CAN_INT_PORT 	PORTD
			#define MX_CAN_INT_TRIS 	TRISD

			//configure remapping
			RPINR28 = (RPINR28 & 0xFF00) | 0x19;	//Assign SDI - RP25 / PORTD4
			RPOR11 = (RPOR11 & 0xFF00) | 0x21;		//Assign SCK - RP22 / PORTD5
			RPOR10 = (RPOR10 & 0xFF00) | 0x20;		//Assign SDO - RP20 / PORTD3

		#else
			#ifdef MX_SPI3_PORT_A
				#define MX_CAN_PORT 		PORTA
				#define MX_CAN_TRIS 		TRISA
				#define MX_CAN_SDO_TRIS 	TRISA
				#define MX_CAN_CS_PORT 		PORTA
				#define MX_CAN_CS_TRIS 		TRISA
				#define MX_CAN_INT_PORT 	PORTA
				#define MX_CAN_INT_TRIS 	TRISA
			#endif
			#ifdef MX_SPI3_PORT_B
				#define MX_CAN_PORT 		PORTB
				#define MX_CAN_TRIS 		TRISB
				#define MX_CAN_SDO_TRIS 	TRISB
				#define MX_CAN_CS_PORT 		PORTB
				#define MX_CAN_CS_TRIS 		TRISB
				#define MX_CAN_INT_PORT 	PORTB
				#define MX_CAN_INT_TRIS 	TRISB
			#endif
			#ifdef MX_SPI3_PORT_C
				#define MX_CAN_PORT 		PORTC
				#define MX_CAN_TRIS 		TRISC
				#define MX_CAN_SDO_TRIS 	TRISC
				#define MX_CAN_CS_PORT 		PORTC
				#define MX_CAN_CS_TRIS 		TRISC
				#define MX_CAN_INT_PORT 	PORTC
				#define MX_CAN_INT_TRIS 	TRISC
			#endif
			#ifdef MX_SPI3_PORT_D
				#define MX_CAN_PORT 		PORTD
				#define MX_CAN_TRIS 		TRISD
				#define MX_CAN_SDO_TRIS 	TRISD
				#define MX_CAN_CS_PORT 		PORTD
				#define MX_CAN_CS_TRIS 		TRISD
				#define MX_CAN_INT_PORT 	PORTD
				#define MX_CAN_INT_TRIS 	TRISD
			#endif
			#ifdef MX_SPI3_PORT_E
				#define MX_CAN_PORT 		PORTE
				#define MX_CAN_TRIS 		TRISE
				#define MX_CAN_SDO_TRIS 	TRISE
				#define MX_CAN_CS_PORT 		PORTE
				#define MX_CAN_CS_TRIS 		TRISE
				#define MX_CAN_INT_PORT 	PORTE
				#define MX_CAN_INT_TRIS 	TRISE
			#endif
			#ifdef MX_SPI3_PORT_F
				#define MX_CAN_PORT 		PORTF
				#define MX_CAN_TRIS 		TRISF
				#define MX_CAN_SDO_TRIS 	TRISF
				#define MX_CAN_CS_PORT 		PORTF
				#define MX_CAN_CS_TRIS 		TRISF
				#define MX_CAN_INT_PORT 	PORTF
				#define MX_CAN_INT_TRIS 	TRISF
			#endif
			#ifdef MX_SPI3_PORT_G
				#define MX_CAN_PORT 		PORTG
				#define MX_CAN_TRIS 		TRISG
				#define MX_CAN_SDO_TRIS 	TRISG
				#define MX_CAN_CS_PORT 		PORTG
				#define MX_CAN_CS_TRIS 		TRISG
				#define MX_CAN_INT_PORT 	PORTG
				#define MX_CAN_INT_TRIS 	TRISG
			#endif
			#define MX_CAN_SDI	MX_SPI3_SDI
			#define MX_CAN_SDO	MX_SPI3_SDO
			#define MX_CAN_SCK	MX_SPI3_SCK
		#endif
	#endif

	//This is the interrupt enable register (set to flag on message received - RX0 and RX1 - and on an error)
	//#define CANINTE_VAL		0x23
	//TODO: should we turn interrupts off, like this:
	//#define CANINTE_VAL		0x00
	//TODO: of just turn on RX interrupts, like this:
	#define CANINTE_VAL		0x03

	// **********************************************************************
	// *              MCP2510 Register Definitions                          *
	// **********************************************************************

	//Configuration Registers
	#define MX_CANSTAT			0x0E
	#define CANCTRL				0x0F
	#define BFPCTRL				0x0C
	#define TEC					0x1C
	#define REC					0x1D
	#define CNF3				0x28
	#define CNF2				0x29
	#define CNF1				0x2A
	#define CANINTE				0x2B
	#define CANINTF				0x2C
	#define EFLG				0x2D
	#define TXRTSCTRL			0x0D

	//Receive Filters
	//NOTE: Use "a" for i={0,1,2} and "b" for i={3,4,5}
	#define RXFxaSIDH(i)			((i*4)+0)
	#define RXFxaSIDL(i)			((i*4)+1)
	#define RXFxaEID8(i)			((i*4)+2)
	#define RXFxaEID0(i)			((i*4)+3)
	#define RXFxbSIDH(i)			((i*4)+4)
	#define RXFxbSIDL(i)			((i*4)+5)
	#define RXFxbEID8(i)			((i*4)+6)
	#define RXFxbEID0(i)			((i*4)+7)
	/*
	#define RXF0SIDH			0x00
	#define RXF0SIDL			0x01
	#define RXF0EID8			0x02
	#define RXF0EID0			0x03
	#define RXF1SIDH			0x04
	#define RXF1SIDL			0x05
	#define RXF1EID8			0x06
	#define RXF1EID0			0x07
	#define RXF2SIDH			0x08
	#define RXF2SIDL			0x09
	#define RXF2EID8			0x0A
	#define RXF2EID0			0x0B
	#define RXF3SIDH			0x10
	#define RXF3SIDL			0x11
	#define RXF3EID8			0x12
	#define RXF3EID0			0x13
	#define RXF4SIDH			0x14
	#define RXF4SIDL			0x15
	#define RXF4EID8			0x16
	#define RXF4EID0			0x17
	#define RXF5SIDH			0x18
	#define RXF5SIDL			0x19
	#define RXF5EID8			0x1A
	#define RXF5EID0			0x1B
	*/

	//Receive Masks
	#define RXMxSIDH(i)			((i*4)+0x20)
	#define RXMxSIDL(i)			((i*4)+0x21)
	#define RXMxEID8(i)			((i*4)+0x22)
	#define RXMxEID0(i)			((i*4)+0x23)

	//Tx Buffers
	#define TXBxCTRL(i)			((i*0x10)+0x30)
	#define TXBxSIDH(i)			((i*0x10)+0x31)
	#define TXBxSIDL(i)			((i*0x10)+0x32)
	#define TXBxEID8(i)			((i*0x10)+0x33)
	#define TXBxEID0(i)			((i*0x10)+0x34)
	#define TXBxDLC(i)			((i*0x10)+0x35)
	#define TXBxD0(i)			((i*0x10)+0x36)
	#define TXBxDy(i,j)			((i*0x10)+0x36+j)

	//Rx Buffers
	#define RXBxCTRL(i)			((i*0x10)+0x60)
	#define RXBxSIDH(i)			((i*0x10)+0x61)
	#define RXBxSIDL(i)			((i*0x10)+0x62)
	#define RXBxEID8(i)			((i*0x10)+0x63)
	#define RXBxEID0(i)			((i*0x10)+0x64)
	#define RXBxDLC(i)			((i*0x10)+0x65)
	#define RXBxD0(i)			((i*0x10)+0x66)
	#define RXBxDy(i,j)			((i*0x10)+0x66+j)


	// *******************************************************************
	// *               Bit register masks                                *
	// *******************************************************************

	//TXBnCTRL
	#define MX_TXREQ			0x08
	#define TXP					0x03

	//RXBnCTRL
	#define RXM					0x60
	#define BUKT				0x04

	//CANCTRL
	#define REQOP				0xE0
	#define MX_ABAT				0x10
	#define CLKEN				0x04
	#define CLKPRE				0x03
	#define OSM					0x08             // (ST) new for the 2515

	//MX_CANSTAT
	#define REQOP				0xE0
	#define ICOD				0x0E

	//CANINTE
	#define RX0IE				0x01
	#define RX1IE				0x02
	#define TX0IE				0x04
	#define TX1IE				0x80
	#define TX2IE				0x10
	#define MX_ERRIE			0x20
	#define MX_WAKIE			0x40
	#define IVMIE				0x80

	//CANINTF
	#define RX0IF				0x01
	#define RX1IF				0x02
	#define TX0IF				0x04
	#define TX1IF				0x80
	#define TX2IF				0x10
	#define MX_ERRIF			0x20
	#define MX_WAKIF			0x40
	#define IVMIF				0x80

	//BFPCTRL
	#define B1BFS				0x20
	#define B0BFS				0x10
	#define B1BFE				0x08
	#define B0BFE				0x04
	#define B1BFM				0x02
	#define B0BFM				0x01

	//CNF1 Masks
	#define SJW					0xC0
	#define BRP					0x3F

	//CNF2 Masks
	#define BTLMODE				0x80
	#define MX_SAM				0x40
	#define PHSEG1				0x38
	#define PRSEG				0x07

	//CNF3 Masks
	#define MX_WAKFIL			0x40
	#define PHSEG2				0x07
	#define SOF					0x80             // (ST) new for the 2515

	//TXRTSCTRL Masks
	#define TXB2RTS				0x04
	#define TXB1RTS				0x02
	#define TXB0RTS				0x01


	// *******************************************************************
	// *                    Bit Timing Configuration                     *
	// *******************************************************************

	//CNF1
	#define SJW_1TQ				0x40
	#define SJW_2TQ				0x80
	#define SJW_3TQ				0x90
	#define SJW_4TQ				0xC0

	//CNF2
	#define BTLMODE_CNF3		0x80
	#define BTLMODE_PH1_IPT		0x00

	#define SMPL_3X				0x40
	#define SMPL_1X				0x00

	#define PHSEG1_8TQ			0x38
	#define PHSEG1_7TQ			0x30
	#define PHSEG1_6TQ			0x28
	#define PHSEG1_5TQ			0x20
	#define PHSEG1_4TQ			0x18
	#define PHSEG1_3TQ			0x10
	#define PHSEG1_2TQ			0x08
	#define PHSEG1_1TQ			0x00

	#define PRSEG_8TQ			0x07
	#define PRSEG_7TQ			0x06
	#define PRSEG_6TQ			0x05
	#define PRSEG_5TQ			0x04
	#define PRSEG_4TQ			0x03
	#define PRSEG_3TQ			0x02
	#define PRSEG_2TQ			0x01
	#define PRSEG_1TQ			0x00

	//CNF3
	#define PHSEG2_8TQ			0x07
	#define PHSEG2_7TQ			0x06
	#define PHSEG2_6TQ			0x05
	#define PHSEG2_5TQ			0x04
	#define PHSEG2_4TQ			0x03
	#define PHSEG2_3TQ			0x02
	#define PHSEG2_2TQ			0x01
	#define PHSEG2_1TQ			0x00

	#define MX_WAKFIL_ENABLED	0x40
	#define MX_WAKFIL_DISABLED	0x00


	// *******************************************************************
	// *                  Control/Configuration Registers                *
	// *******************************************************************

	//CANINTE
	#define RX0IE_ENABLED		0x01
	#define RX0IE_DISABLED		0x00
	#define RX1IE_ENABLED		0x02
	#define RX1IE_DISABLED		0x00
	#define G_RXIE_ENABLED		0x03
	#define G_RXIE_DISABLED		0x00

	#define TX0IE_ENABLED		0x04
	#define TX0IE_DISABLED		0x00
	#define TX1IE_ENABLED		0x08
	#define TX2IE_DISABLED		0x00
	#define TX2IE_ENABLED		0x10
	#define TX2IE_DISABLED		0x00
	#define G_TXIE_ENABLED		0x1C
	#define G_TXIE_DISABLED		0x00

	#define MX_ERRIE_ENABLED	0x20
	#define MX_ERRIE_DISABLED	0x00
	#define MX_WAKIE_ENABLED	0x40
	#define MX_WAKIE_DISABLED	0x00
	#define IVRE_ENABLED		0x80
	#define IVRE_DISABLED		0x00

	//CANINTF
	#define RX0IF_SET			0x01
	#define RX0IF_RESET			0x00
	#define RX1IF_SET			0x02
	#define RX1IF_RESET			0x00
	#define TX0IF_SET			0x04
	#define TX0IF_RESET			0x00
	#define TX1IF_SET			0x08
	#define TX2IF_RESET			0x00
	#define TX2IF_SET			0x10
	#define TX2IF_RESET			0x00
	#define MX_ERRIF_SET		0x20
	#define MX_ERRIF_RESET		0x00
	#define MX_WAKIF_SET		0x40
	#define MX_WAKIF_RESET		0x00
	#define IVRF_SET			0x80
	#define IVRF_RESET			0x00


	#define ABORT				0x10

	#define CLKOUT_ENABLED		0x04
	#define CLKOUT_DISABLED		0x00
	#define CLKOUT_PRE_8		0x03
	#define CLKOUT_PRE_4		0x02
	#define CLKOUT_PRE_2		0x01
	#define CLKOUT_PRE_1		0x00

	//MX_CANSTAT
	#define OPMODE_CONFIG		0x80
	#define OPMODE_LISTEN		0x60
	#define OPMODE_LOOPBACK		0x40
	#define OPMODE_SLEEP		0x20
	#define OPMODE_NORMAL		0x00


	//RXBnCTRL
	#define RXM_RCV_ALL			0x60
	#define RXM_VALID_EXT		0x40
	#define RXM_VALID_STD		0x20
	#define RXM_VALID_ALL		0x00

	#define RXRTR_REMOTE		0x08
	#define RXRTR_NO_REMOTE		0x00

	#define BUKT_ROLLOVER		0x04
	#define BUKT_NO_ROLLOVER	0x00

	#define FILHIT0_FLTR_1		0x01
	#define FILHIT0_FLTR_0		0x00

	#define FILHIT1_FLTR_5		0x05
	#define FILHIT1_FLTR_4		0x04
	#define FILHIT1_FLTR_3		0x03
	#define FILHIT1_FLTR_2		0x02
	#define FILHIT1_FLTR_1		0x01
	#define FILHIT1_FLTR_0		0x00


	//TXBnCTRL
	#define MX_TXREQ_SEND		0x08
	#define MX_TXREQ_ABORT		0x00

	#define TXP_HIGHEST			0x03
	#define TXP_INTER_HIGH		0x02
	#define TXP_INTER_LOW		0x01
	#define TXP_LOWEST			0x00


	// *******************************************************************
	// *                  Register Bit Masks                             *
	// *******************************************************************

	#define DLC_0				0x00
	#define DLC_1				0x01
	#define DLC_2				0x02
	#define DLC_3				0x03
	#define DLC_4				0x04
	#define DLC_5				0x05
	#define DLC_6				0x06
	#define DLC_7				0x07
	#define DLC_8				0x08


	// *******************************************************************
	// *                  CAN SPI commands                               *
	// *******************************************************************

	#define CAN_RESET			0xC0
	#define CAN_READ			0x03
	#define CAN_WRITE			0x02
	#define CAN_RD_STATUS		0xA0
	#define CAN_BIT_MODIFY		0x05

	#define CAN_RTS				0x80
	#define CAN_RTS_TXB0		0x81
	#define CAN_RTS_TXB1		0x82
	//#define CAN_RTS_TXB2		0x83          // (ST) I think this is wrong..so I changed it to this:
	#define CAN_RTS_TXB2		0x84
	//#define CAN_RTS_TXB(i)		(0x80 + (0x01 << i))
	//NOTE: the above line does not work because the RHS of a shift cannot be a variable

	// (ST) I also added these for multiple requests...
	#define CAN_RTS_TXB01		0x83
	#define CAN_RTS_TXB02		0x85
	#define CAN_RTS_TXB12		0x86
	#define CAN_RTS_TXB012		0x87

	#define CAN_RX_STATUS		0xB0

	#define CAN_RD_RXBUF_ID(i)	(0x90 + (i*4))
	#define CAN_RD_RXBUF_DT(i)	(0x92 + (i*4))

	#define CAN_LD_TXBUF_ID(i)	(0x40 + (i*2))
	#define CAN_LD_TXBUF_DT(i)	(0x41 + (i*2))

#endif

// *******************************************************************
// *                  Miscellaneous                                  *
// *******************************************************************


//uncomment this if supporting extended identifiers:
//#define CAN_USE_EXID

/*DefinesCode_End*/

/*InitialisationCode_Start*/
/*InitialisationCode_End*/

/*InterruptCode_Start*/
/*InterruptCode_End*/

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

//internal function implementations
void SPI_Init()
{
/*Macro_SPI_Init_Start*/

#ifndef USE_INT_CAN

	//initialise spi
	set_bit(MX_CAN_TRIS,MX_CAN_SDI);
	clear_bit(MX_CAN_SDO_TRIS,MX_CAN_SDO);
	clear_bit(MX_CAN_TRIS,MX_CAN_SCK);
	clear_bit(MX_CAN_CS_TRIS,CAN_CHIPSEL);
	set_bit(MX_CAN_INT_TRIS,CAN_INTERRUPT);

	//disable the CAN chip select line
	set_bit(MX_CAN_CS_PORT, CAN_CHIPSEL);

	//setup SPI peripheral
	#if (CAN_SPI_PORT == 1)
		SPI1CON1 = SPISPEED;
		SPI1CON1bits.CKE = 1;
		SPI1CON1bits.MSTEN = 1;		//master mode
		SPI1STATbits.SPIROV = 0;	//clear unread data flag
		SPI1STATbits.SPIEN = 1;		//enable SPI peripheral
	#endif

	#if (CAN_SPI_PORT == 2)
		SPI2CON1 = SPISPEED;
		SPI2CON1bits.CKE = 1;
		SPI2CON1bits.MSTEN = 1;		//master mode
		SPI2STATbits.SPIROV = 0;	//clear unread data flag
		SPI2STATbits.SPIEN = 1;		//enable SPI peripheral
	#endif

	#if (CAN_SPI_PORT == 3)
		SPI3CON1 = SPISPEED;
		SPI3CON1bits.CKE = 1;
		SPI3CON1bits.MSTEN = 1;		//master mode
		SPI3STATbits.SPIROV = 0;	//clear unread data flag
		SPI3STATbits.SPIEN = 1;		//enable SPI peripheral
	#endif

#endif

/*Macro_SPI_Init_End*/
}


char SPI_SendByte(char byte)
{
/*Macro_SPI_SendByte_Start*/

	char retVal = 0;

#ifndef USE_INT_CAN

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

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

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

#endif

	return retVal;

/*Macro_SPI_SendByte_End*/
}


char CAN_MaskFromBit(char which_bit)
{
/*Macro_CAN_MaskFromBit_Start*/
	char retVal = 0;
	switch (which_bit)
	{
		case 0:
			retVal = 0x01;
			break;

		case 1:
			retVal = 0x02;
			break;

		case 2:
			retVal = 0x04;
			break;

		case 3:
			retVal = 0x08;
			break;

		case 4:
			retVal = 0x10;
			break;

		case 5:
			retVal = 0x20;
			break;

		case 6:
			retVal = 0x40;
			break;

		case 7:
			retVal = 0x80;
			break;
	}
	return (retVal);
/*Macro_CAN_MaskFromBit_End*/
}


void CAN_Reset()
{
/*Macro_CAN_Reset_Start*/

#ifndef USE_INT_CAN

	//enable SPI
	clear_bit(MX_CAN_CS_PORT, CAN_CHIPSEL);

	SPI_SendByte(CAN_RESET);

	//disable SPI
	set_bit(MX_CAN_CS_PORT, CAN_CHIPSEL);

	//wait for the CAN device to complete its OST
	delay_us(20);

#endif

/*Macro_CAN_Reset_End*/
}


void CAN_Write(char addr, char data)
{
/*Macro_CAN_Write_Start*/

#ifndef USE_INT_CAN

	//enable SPI
	clear_bit(MX_CAN_CS_PORT, CAN_CHIPSEL);

	SPI_SendByte(CAN_WRITE);			//send a byte
	SPI_SendByte(addr);					//send the address
	SPI_SendByte(data);					//send the data

	//disable SPI
	set_bit(MX_CAN_CS_PORT, CAN_CHIPSEL);

#endif

/*Macro_CAN_Write_End*/
}


char CAN_Read(char addr)
{
/*Macro_CAN_Read_Start*/

	char data;

#ifndef USE_INT_CAN

	//enable SPI
	clear_bit(MX_CAN_CS_PORT, CAN_CHIPSEL);

	SPI_SendByte(CAN_READ);				//read a byte
	SPI_SendByte(addr);					//send the address
	data = SPI_SendByte(0x5A);			//send a don't care byte

	//disable SPI
	set_bit(MX_CAN_CS_PORT, CAN_CHIPSEL);

#endif

	return (data);

/*Macro_CAN_Read_End*/
}


void CAN_Config(char cfg)
{
/*Macro_CAN_Config_Start*/

#ifndef USE_INT_CAN

	char mode;
	char done = 0;

	while (done == 0)
	{
		CAN_Write(CANCTRL, cfg);

		Wdt_Delay_Ms(1);				//not sure if this is needed

		//read the config mode back
		mode = CAN_Read(MX_CANSTAT);

		//mask off the config bits
		mode = mode & 0xE0;

		if (mode == cfg)
		{
			//it has been set correctly
			done = 1;
		}
	}

	Wdt_Delay_Ms(1);				//not sure if this is needed

#endif

/*Macro_CAN_Config_End*/
}


char CAN_ReadStatus()
{
/*Macro_CAN_ReadStatus_Start*/

	char retval = 0;

#ifndef USE_INT_CAN

	//enable SPI
	clear_bit(MX_CAN_CS_PORT, CAN_CHIPSEL);

	SPI_SendByte(CAN_RD_STATUS);		//read the status
	retval = SPI_SendByte(0x5A);		//send a don't care byte

	//disable SPI
	set_bit(MX_CAN_CS_PORT, CAN_CHIPSEL);

#endif

	return (retval);

/*Macro_CAN_ReadStatus_End*/
}


char CAN_ReadRXStatus()
{
/*Macro_CAN_ReadRXStatus_Start*/

	char retval = 0;

#ifndef USE_INT_CAN

	//enable SPI
	clear_bit(MX_CAN_CS_PORT, CAN_CHIPSEL);

	SPI_SendByte(CAN_RX_STATUS);		//read the status
	retval = SPI_SendByte(0x5A);		//send a don't care byte

	//disable SPI
	set_bit(MX_CAN_CS_PORT, CAN_CHIPSEL);

#endif

	return (retval);

/*Macro_CAN_ReadRXStatus_End*/
}


void CAN_BitModify(char addr, char mask, char data)
{
/*Macro_CAN_BitModify_Start*/

#ifndef USE_INT_CAN

	//enable SPI
	clear_bit(MX_CAN_CS_PORT, CAN_CHIPSEL);

	SPI_SendByte(CAN_BIT_MODIFY);		//bit modify
	SPI_SendByte(addr);					//send the address
	SPI_SendByte(mask);					//send the mask
	SPI_SendByte(data);					//send the data

	//disable SPI
	set_bit(MX_CAN_CS_PORT, CAN_CHIPSEL);

#endif

/*Macro_CAN_BitModify_End*/
}


char CAN_ReadRX_ID_and_Data(char buffer)
{
/*Macro_CAN_ReadRX_ID_and_Data_Start*/

	//populates CAN_MSG_ID[], CAN_MSG_DLC, and CAN_MSG_DATA[], and returns CAN_MSG_DLC
	char idx = 0;

	if (buffer > CAN_MAX_RX_BUF)
	{
		return (0);
	}

	#ifndef USE_INT_CAN

		//enable SPI
		clear_bit(MX_CAN_CS_PORT, CAN_CHIPSEL);

		SPI_SendByte(CAN_RD_RXBUF_ID(buffer));		//read the RX ID

		CAN_MSG_ID[idx++] = SPI_SendByte(0x5A);		//read back SIDH

		CAN_MSG_ID[idx++] = SPI_SendByte(0x5A);		//read back SIDL

	  #ifdef CAN_USE_EXID
		CAN_MSG_ID[idx++] = SPI_SendByte(0x5A);		//read back EXID8
	  #else
	  	SPI_SendByte(0x5A);
	  #endif

	  #ifdef CAN_USE_EXID
		CAN_MSG_ID[idx++] = SPI_SendByte(0x5A);		//read back EXID0
	  #else
	  	SPI_SendByte(0x5A);
	  #endif

		CAN_MSG_DLC = SPI_SendByte(0x5A);			//read back DLC

		//now read the data (if there is any)
		if (CAN_MSG_DLC > 0)
		{
			CAN_MSG_DATA[0] = SPI_SendByte(0x5A);		//read back D0

			if (CAN_MSG_DLC > 1)
			{
				CAN_MSG_DATA[1] = SPI_SendByte(0x5A);			//read back D1

				if (CAN_MSG_DLC > 2)
				{
					CAN_MSG_DATA[2] = SPI_SendByte(0x5A);			//read back D2

					if (CAN_MSG_DLC > 3)
					{
						CAN_MSG_DATA[3] = SPI_SendByte(0x5A);			//read back D3

						if (CAN_MSG_DLC > 4)
						{
							CAN_MSG_DATA[4] = SPI_SendByte(0x5A);			//read back D4

							if (CAN_MSG_DLC > 5)
							{
								CAN_MSG_DATA[5] = SPI_SendByte(0x5A);			//read back D5

								if (CAN_MSG_DLC > 6)
								{
									CAN_MSG_DATA[6] = SPI_SendByte(0x5A);			//read back D6

									if (CAN_MSG_DLC > 7)
									{
										CAN_MSG_DATA[7] = SPI_SendByte(0x5A);			//read back D7
									}
								}
							}
						}
					}
				}
			}
		}

		//disable SPI
		set_bit(MX_CAN_CS_PORT, CAN_CHIPSEL);

	#endif

	return (CAN_MSG_DLC);
/*Macro_CAN_ReadRX_ID_and_Data_End*/
}


void Init()
{
/*Macro_Init_Start*/

#ifdef USE_INT_CAN

	#ifndef dsPIC30	//Non dsPIC30F Device - Internal CAN different!!!
		#error "Internal CAN is not supported in the device type. dsPIC30 only supported."
	#endif

	//configure CAN I/O - ds30F??

    // Request config mode.
    C1CTRL = REQOP_CONFIG;

	// Wait till desired mode is set.
    while( (C1CTRL & CAN_OP_MODE_BITS) != 0x80 );

    // Now set the baud rate.
	C1CFG2 = CNF2_VAL | (CNF3_VAL << 8);
	C1CFG1 = CNF1_VAL;

	//Setup the CAN comms Masks and Filters
	C1RXF0SID = (RXF0SIDH_VAL << 5) | (RXF0SIDL_VAL >> 3);    									// ID Filter 0 - Buffer 0
	C1RXF0EIDL = (RXF0EID0_VAL << 10);
	C1RXF0EIDH = (RXF0EID0_VAL >> 6) | (RXF0EID8_VAL << 6) | ((RXF0SIDL_VAL & 0x03) << 10);
	C1RXF1SID = (RXF1SIDH_VAL << 5) | (RXF1SIDL_VAL >> 3);    									// ID Filter 1 - Buffer 0
	C1RXF1EIDL = (RXF1EID0_VAL << 10);
	C1RXF1EIDH = (RXF1EID0_VAL >> 6) | (RXF1EID8_VAL << 6) | ((RXF1SIDL_VAL & 0x03) << 10);
	C1RXM0SID = (RXM0SIDH_VAL << 5) | (RXM0SIDL_VAL >> 3);										// ID Mask 0 - Buffer 0
	C1RXM0EIDL = (RXM0EID0_VAL << 10);
	C1RXM0EIDH = (RXM0EID0_VAL >> 6) | (RXF1EID8_VAL << 6) | ((RXM0SIDL_VAL & 0x03) << 10);

	C1RXF2SID = (RXF2SIDH_VAL << 5) | (RXF2SIDL_VAL >> 3);    									// ID Filter 2 - Buffer 1
	C1RXF2EIDL = (RXF2EID0_VAL << 10);
	C1RXF2EIDH = (RXF2EID0_VAL >> 6) | (RXF2EID8_VAL << 6) | ((RXF2SIDL_VAL & 0x03) << 10);
	C1RXF3SID = (RXF3SIDH_VAL << 5) | (RXF3SIDL_VAL >> 3);    									// ID Filter 3 - Buffer 1
	C1RXF3EIDL = (RXF3EID0_VAL << 10);
	C1RXF3EIDH = (RXF3EID0_VAL >> 6) | (RXF3EID8_VAL << 6) | ((RXF3SIDL_VAL & 0x03) << 10);
	C1RXF4SID = (RXF4SIDH_VAL << 5) | (RXF4SIDL_VAL >> 3);    									// ID Filter 4 - Buffer 1
	C1RXF4EIDL = (RXF4EID0_VAL << 10);
	C1RXF4EIDH = (RXF4EID0_VAL >> 6) | (RXF4EID8_VAL << 6) | ((RXF4SIDL_VAL & 0x03) << 10);
	C1RXF5SID = (RXF5SIDH_VAL << 5) | (RXF5SIDL_VAL >> 3);										// ID Filter 5 - Buffer 1
	C1RXF5EIDL = (RXF5EID0_VAL << 10);
	C1RXF5EIDH = (RXF5EID0_VAL >> 6) | (RXF5EID8_VAL << 6) | ((RXF5SIDL_VAL & 0x03) << 10);
	C1RXM1SID = (RXM0SIDH_VAL << 5) | (RXM1SIDL_VAL >> 3);										// ID Mask 1 - Buffer 1
	C1RXM1EIDL = (RXM1EID0_VAL << 10);
	C1RXM1EIDH = (RXM1EID0_VAL >> 6) | (RXM1EID8_VAL << 6) | ((RXM1SIDL_VAL & 0x03) << 10);

	C1RX0CON = RXB0CTRL_VAL;    // Receive Buffer 0 Control
	C1RX1CON = RXB1CTRL_VAL;	// Receive Buffer 1 Control

	C1TX0CON = TXB0CTRL_VAL;	// Transmit Buffer 0 Control

	C1TX0SID = ((TXB0SIDH_VAL << 5) | (TXB0SIDL_VAL >> 3)) & 0x00FF;	//Transmit Preload S-ID
	C1TX0SID = C1TX0SID | ((TXB0SIDH_VAL << 8) & 0xFF00);

	C1TX0EID = ((TXB0EID0_VAL >> 6) | (TXB0EID8_VAL << 2)) & 0x00FF;	//Transmit Preload E-ID
	C1TX0EID = C1TX0EID | (((TXB0EID8_VAL & 0xC0) << 6) | (TXB0SIDL_VAL << 14));
	C1TX0DLC = (TXB0EID0_VAL << 10) | (TXB0DLC_VAL << 3);

	C1TX0B1 = (TXB0DB1_VAL << 8) | TXB0DB0_VAL;							// Transmit Data Bytes
	C1TX0B2 = (TXB0DB3_VAL << 8) | TXB0DB2_VAL;
	C1TX0B3 = (TXB0DB5_VAL << 8) | TXB0DB4_VAL;
	C1TX0B4 = (TXB0DB7_VAL << 8) | TXB0DB6_VAL;

	C1TX1CON = TXB1CTRL_VAL;	// Transmit Buffer 1 Control

	C1TX1SID = ((TXB1SIDH_VAL << 5) | (TXB1SIDL_VAL >> 3)) & 0x00FF;	//Transmit Preload S-ID
	C1TX1SID = C1TX1SID | ((TXB1SIDH_VAL << 8) & 0xFF00);

	C1TX1EID = ((TXB1EID0_VAL >> 6) | (TXB1EID8_VAL << 2)) & 0x00FF;	//Transmit Preload E-ID
	C1TX1EID = C1TX1EID | (((TXB1EID8_VAL & 0xC0) << 6) | (TXB1SIDL_VAL << 14));
	C1TX1DLC = (TXB1EID0_VAL << 10) | (TXB1DLC_VAL << 3);

	C1TX1B1 = (TXB1DB1_VAL << 8) | TXB1DB0_VAL;							// Transmit Data Bytes
	C1TX1B2 = (TXB1DB3_VAL << 8) | TXB1DB2_VAL;
	C1TX1B3 = (TXB1DB5_VAL << 8) | TXB1DB4_VAL;
	C1TX1B4 = (TXB1DB7_VAL << 8) | TXB1DB6_VAL;

	C1TX2CON = TXB2CTRL_VAL;	// Transmit Buffer 2 Control

	C1TX2SID = ((TXB2SIDH_VAL << 5) | (TXB2SIDL_VAL >> 3)) & 0x00FF;	//Transmit Preload S-ID
	C1TX2SID = C1TX2SID | ((TXB2SIDH_VAL << 8) & 0xFF00);

	C1TX2EID = ((TXB2EID0_VAL >> 6) | (TXB2EID8_VAL << 2)) & 0x00FF;	//Transmit Preload E-ID
	C1TX2EID = C1TX2EID | (((TXB2EID8_VAL & 0xC0) << 6) | (TXB2SIDL_VAL << 14));
	C1TX2DLC = (TXB2EID0_VAL << 10) | (TXB2DLC_VAL << 3);

	C1TX2B1 = (TXB2DB1_VAL << 8) | TXB2DB0_VAL;							// Transmit Data Bytes
	C1TX2B2 = (TXB2DB3_VAL << 8) | TXB2DB2_VAL;
	C1TX2B3 = (TXB2DB5_VAL << 8) | TXB2DB4_VAL;
	C1TX2B4 = (TXB2DB7_VAL << 8) | TXB2DB6_VAL;

    // Request normal mode.
    C1CTRL = REQOP_NORMAL;

	// Wait till desired mode is set.
    while( (C1CTRL & CAN_OP_MODE_BITS) != 0x00 );

#else

	//Init SPI
	SPI_Init();

	//brief pause here
	Wdt_Delay_Ms(50);

	//Reset the CAN device
	CAN_Reset();

	//Put the CAN device into config mode
	CAN_Config(REQOP_CONFIG);

	//Initialise all the CAN device registers
	//enable SPI
	clear_bit(MX_CAN_CS_PORT, CAN_CHIPSEL);

	SPI_SendByte(CAN_WRITE);        //CAN write mode
	SPI_SendByte(0x00);             //start writting at address 0x00

	SPI_SendByte(RXF0SIDH_VAL);     // RXF0SIDH  0x00
	SPI_SendByte(RXF0SIDL_VAL);     // RXF0SIDL  0x01
	SPI_SendByte(RXF0EID8_VAL);     // RXF0EID8  0x02
	SPI_SendByte(RXF0EID0_VAL);     // RXF0EID0  0x03
	SPI_SendByte(RXF1SIDH_VAL);     // RXF1SIDH  0x04
	SPI_SendByte(RXF1SIDL_VAL);     // RXF1SIDL  0x05
	SPI_SendByte(RXF1EID8_VAL);     // RXF1EID8  0x06
	SPI_SendByte(RXF1EID0_VAL);     // RXF1EID0  0x07
	SPI_SendByte(RXF2SIDH_VAL);     // RXF2SIDH  0x08
	SPI_SendByte(RXF2SIDL_VAL);     // RXF2SIDL  0x09
	SPI_SendByte(RXF2EID8_VAL);     // RXF2EID8  0x0A
	SPI_SendByte(RXF2EID0_VAL);     // RXF2EID0  0x0B
	SPI_SendByte(BFPCTRL_VAL);      // BFPCTRL   0x0C
	SPI_SendByte(TXRTSCTRL_VAL);    // TXRTSCTRL 0x0D
	SPI_SendByte(MX_CANSTAT_VAL);   // MX_CANSTAT   0x0E
	SPI_SendByte(CANCTRL_VAL);      // CANCTRL   0x0F

	SPI_SendByte(RXF3SIDH_VAL);     // RXF3SIDH  0x10
	SPI_SendByte(RXF3SIDL_VAL);     // RXF3SIDL  0x11
	SPI_SendByte(RXF3EID8_VAL);     // RXF3EID8  0x12
	SPI_SendByte(RXF3EID0_VAL);     // RXF3EID0  0x13
	SPI_SendByte(RXF4SIDH_VAL);     // RXF4SIDH  0x14
	SPI_SendByte(RXF4SIDL_VAL);     // RXF4SIDL  0x15
	SPI_SendByte(RXF4EID8_VAL);     // RXF4EID8  0x16
	SPI_SendByte(RXF4EID0_VAL);     // RXF4EID0  0x17
	SPI_SendByte(RXF5SIDH_VAL);     // RXF5SIDH  0x18
	SPI_SendByte(RXF5SIDL_VAL);     // RXF5SIDL  0x19
	SPI_SendByte(RXF5EID8_VAL);     // RXF5EID8  0x1A
	SPI_SendByte(RXF5EID0_VAL);     // RXF5EID0  0x1B
	SPI_SendByte(0x00);             // TEC       0x1C
	SPI_SendByte(0x00);             // REC       0x1D
	SPI_SendByte(MX_CANSTAT_VAL);   // MX_CANSTAT   0x1E
	SPI_SendByte(CANCTRL_VAL);      // CANCTRL   0x1F

	SPI_SendByte(RXM0SIDH_VAL);     // RXM0SIDH  0x20
	SPI_SendByte(RXM0SIDL_VAL);     // RXM0SIDL  0x21
	SPI_SendByte(RXM0EID8_VAL);     // RXM0EID8  0x22
	SPI_SendByte(RXM0EID0_VAL);     // RXM0EID0  0x23
	SPI_SendByte(RXM1SIDH_VAL);     // RXM1SIDH  0x20
	SPI_SendByte(RXM1SIDL_VAL);     // RXM1SIDL  0x21
	SPI_SendByte(RXM1EID8_VAL);     // RXM1EID8  0x26
	SPI_SendByte(RXM1EID0_VAL);     // RXM1EID0  0x27
	SPI_SendByte(CNF3_VAL);         // CNF3      0x28
	SPI_SendByte(CNF2_VAL);         // CNF2      0x29
	SPI_SendByte(CNF1_VAL);         // CNF1      0x2A
	SPI_SendByte(CANINTE_VAL);      // CANINTE   0x2B
	SPI_SendByte(0x00);             // CANINTF   0x2C
	SPI_SendByte(0x00);             // EFLG      0x2D
	SPI_SendByte(MX_CANSTAT_VAL);   // MX_CANSTAT   0x2E
	SPI_SendByte(CANCTRL_VAL);      // CANCTRL   0x2F

	SPI_SendByte(TXB0CTRL_VAL);     // TXB0CTRL  0x30
	SPI_SendByte(TXB0SIDH_VAL);     // TXB0SIDH  0x31
	SPI_SendByte(TXB0SIDL_VAL);     // TXB0SIDL  0x32
	SPI_SendByte(TXB0EID8_VAL);     // TXB0EID8  0x33
	SPI_SendByte(TXB0EID0_VAL);     // TXB0EID0  0x34
	SPI_SendByte(TXB0DLC_VAL);      // TXB0DLC   0x35
	SPI_SendByte(TXB0DB0_VAL);      // TXB0DB0   0x36
	SPI_SendByte(TXB0DB1_VAL);      // TXB0DB1   0x37
	SPI_SendByte(TXB0DB2_VAL);      // TXB0DB2   0x38
	SPI_SendByte(TXB0DB3_VAL);      // TXB0DB3   0x39
	SPI_SendByte(TXB0DB4_VAL);      // TXB0DB4   0x3A
	SPI_SendByte(TXB0DB5_VAL);      // TXB0DB5   0x3B
	SPI_SendByte(TXB0DB6_VAL);      // TXB0DB6   0x3C
	SPI_SendByte(TXB0DB7_VAL);      // TXB0DB7   0x3D
	SPI_SendByte(MX_CANSTAT_VAL);   // MX_CANSTAT   0x3E
	SPI_SendByte(CANCTRL_VAL);      // CANCTRL   0x3F

	SPI_SendByte(TXB1CTRL_VAL);     // TXB1CTRL  0x40 Highest priority
	SPI_SendByte(TXB1SIDH_VAL);     // TXB1SIDH  0x41
	SPI_SendByte(TXB1SIDL_VAL);     // TXB1SIDL  0x42
	SPI_SendByte(TXB1EID8_VAL);     // TXB1EID8  0x43
	SPI_SendByte(TXB1EID0_VAL);     // TXB1EID0  0x44
	SPI_SendByte(TXB1DLC_VAL);      // TXB1DLC   0x45
	SPI_SendByte(TXB1DB0_VAL);      // TXB1DB0   0x46
	SPI_SendByte(TXB1DB1_VAL);      // TXB1DB1   0x47
	SPI_SendByte(TXB1DB2_VAL);      // TXB1DB2   0x48
	SPI_SendByte(TXB1DB3_VAL);      // TXB1DB3   0x49
	SPI_SendByte(TXB1DB4_VAL);      // TXB1DB4   0x4A
	SPI_SendByte(TXB1DB5_VAL);      // TXB1DB5   0x4B
	SPI_SendByte(TXB1DB6_VAL);      // TXB1DB6   0x4C
	SPI_SendByte(TXB1DB7_VAL);      // TXB1DB7   0x4D
	SPI_SendByte(MX_CANSTAT_VAL);   // MX_CANSTAT   0x4E
	SPI_SendByte(CANCTRL_VAL);      // CANCTRL   0x4F

	SPI_SendByte(TXB2CTRL_VAL);     // TXB2CTRL  0x50
	SPI_SendByte(TXB2SIDH_VAL);     // TXB2SIDH  0x51
	SPI_SendByte(TXB2SIDL_VAL);     // TXB2SIDL  0x52
	SPI_SendByte(TXB2EID8_VAL);     // TXB2EID8  0x53
	SPI_SendByte(TXB2EID0_VAL);     // TXB2EID0  0x54
	SPI_SendByte(TXB2DLC_VAL);      // TXB2DLC   0x55
	SPI_SendByte(TXB2DB0_VAL);      // TXB2DB0   0x56
	SPI_SendByte(TXB2DB1_VAL);      // TXB2DB1   0x57
	SPI_SendByte(TXB2DB2_VAL);      // TXB2DB2   0x58
	SPI_SendByte(TXB2DB3_VAL);      // TXB2DB3   0x59
	SPI_SendByte(TXB2DB4_VAL);      // TXB2DB4   0x5A
	SPI_SendByte(TXB2DB5_VAL);      // TXB2DB5   0x5B
	SPI_SendByte(TXB2DB6_VAL);      // TXB2DB6   0x5C
	SPI_SendByte(TXB2DB7_VAL);      // TXB2DB7   0x5D
	SPI_SendByte(MX_CANSTAT_VAL);   // MX_CANSTAT   0x5E
	SPI_SendByte(CANCTRL_VAL);      // CANCTRL   0x5F

	SPI_SendByte(RXB0CTRL_VAL);     // RXB0CTRL  0x60
	SPI_SendByte(0x00);             // RXB0SIDH  0x61
	SPI_SendByte(0x00);             // RXB0SIDL  0x62
	SPI_SendByte(0x00);             // RXB0EID8  0x63
	SPI_SendByte(0x00);             // RXB0EID0  0x64
	SPI_SendByte(0x00);             // RXB0DLC   0x65
	SPI_SendByte(0x00);             // RXB0DB0   0x66
	SPI_SendByte(0x00);             // RXB0DB1   0x67
	SPI_SendByte(0x00);             // RXB0DB2   0x68
	SPI_SendByte(0x00);             // RXB0DB3   0x69
	SPI_SendByte(0x00);             // RXB0DB4   0x6A
	SPI_SendByte(0x00);             // RXB0DB5   0x6B
	SPI_SendByte(0x00);             // RXB0DB6   0x6C
	SPI_SendByte(0x00);             // RXB0DB7   0x6D
	SPI_SendByte(MX_CANSTAT_VAL);   // MX_CANSTAT   0x6E
	SPI_SendByte(CANCTRL_VAL);      // CANCTRL   0x6F

	SPI_SendByte(RXB1CTRL_VAL);     // RXB1CTRL  0x70
	SPI_SendByte(0x00);             // RXB1SIDH  0x71
	SPI_SendByte(0x00);             // RXB1SIDL  0x72
	SPI_SendByte(0x00);             // RXB1EID8  0x73
	SPI_SendByte(0x00);             // RXB1EID0  0x74
	SPI_SendByte(0x00);             // RXB1DLC   0x75
	SPI_SendByte(0x00);             // RXB1DB0   0x76
	SPI_SendByte(0x00);             // RXB1DB1   0x77
	SPI_SendByte(0x00);             // RXB1DB2   0x78
	SPI_SendByte(0x00);             // RXB1DB3   0x79
	SPI_SendByte(0x00);             // RXB1DB4   0x7A
	SPI_SendByte(0x00);             // RXB1DB5   0x7B
	SPI_SendByte(0x00);             // RXB1DB6   0x7C
	SPI_SendByte(0x00);             // RXB1DB7   0x7D
	SPI_SendByte(MX_CANSTAT_VAL);   // MX_CANSTAT   0x7E
	SPI_SendByte(CANCTRL_VAL);      // CANCTRL   0x7F

	//disable SPI
	set_bit(MX_CAN_CS_PORT, CAN_CHIPSEL);

	//Put the CAN device into normal mode
	CAN_Config(REQOP_NORMAL);

#endif

/*Macro_Init_End*/
}


void SendBuffer(char buffer)
{
/*Macro_SendBuffer_Start*/

	if (buffer > CAN_MAX_TX_BUF)
	{
	   return;
	}

	#ifdef USE_INT_CAN

		unsigned int timeout = 0xFFFF;

		switch (buffer)
		{
			case 0:
				C1TX0CONbits.TXREQ = 1;							//Set Message Transmission Flag
				while (C1TX0CONbits.TXREQ && timeout)			//Wait for message to send
					timeout = timeout - 1;
				break;
			case 1:
				C1TX1CONbits.TXREQ = 1;
				while (C1TX1CONbits.TXREQ && timeout)
					timeout = timeout - 1;
				break;
			case 2:
				C1TX2CONbits.TXREQ = 1;
				while (C1TX2CONbits.TXREQ && timeout)
					timeout = timeout - 1;
				break;
		}

	#else

		char cmd = CAN_RTS;         //default value

		switch (buffer)
		{
		   case 0:
			   cmd = CAN_RTS_TXB0;
			   break;

		   case 1:
			   cmd = CAN_RTS_TXB1;
			   break;

		   case 2:
			   cmd = CAN_RTS_TXB2;
			   break;
		}
		//NOTE: this following didn't work:
		//cmd = CAN_RTS_TXB(buffer);

		//enable SPI
		clear_bit(MX_CAN_CS_PORT, CAN_CHIPSEL);

		SPI_SendByte(cmd);

		//disable SPI
		set_bit(MX_CAN_CS_PORT, CAN_CHIPSEL);

	#endif

/*Macro_SendBuffer_End*/
}


char CheckRx(char buffer)
{
/*Macro_CheckRx_Start*/

	//returns 1 if the buffer is full, 0 otherwise
	char rx_status;
	char status_mask;
	char retval = 0;

	if (buffer > CAN_MAX_RX_BUF)
	{
	   return (0);
	}

#ifdef USE_INT_CAN

	if (buffer == 0)
	{
		if (C1RX0CONbits.RXFUL)
		{
			CAN_MSG_DLC = C1RX0DLC & 0x000F;	// Retrieve message length.
			CAN_MSG_ID[0] = C1RX0SID >> 5;
			CAN_MSG_ID[1] = C1RX0SID << 3;

			if(CAN_MSG_DLC > 0)
			{
				CAN_MSG_DATA[0] = C1RX0B1 & 0xFF;
				if(CAN_MSG_DLC > 1)
				{
					CAN_MSG_DATA[1] = C1RX0B1 >> 8;
					if(CAN_MSG_DLC > 2)
					{
						CAN_MSG_DATA[2] = C1RX0B2 & 0xFF;
						if(CAN_MSG_DLC > 3)
						{
							CAN_MSG_DATA[3] = C1RX0B2 >> 8;
							if(CAN_MSG_DLC > 4)
							{
								CAN_MSG_DATA[4] = C1RX0B3 & 0xFF;
								if(CAN_MSG_DLC > 5)
								{
									CAN_MSG_DATA[5] = C1RX0B3 >> 8;
									if(CAN_MSG_DLC > 6)
									{
										CAN_MSG_DATA[6] = C1RX0B4 & 0xFF;
										if(CAN_MSG_DLC > 7)
										{
											CAN_MSG_DATA[7] = C1RX0B4 >> 8;
										}
									}
								}
							}
						}
					}
				}
			}
			C1RX0CONbits.RXFUL = 0;
		}
		else
			return 0;
	}
	else
	{
		if (C1RX1CONbits.RXFUL)
		{
			CAN_MSG_DLC = C1RX1DLC & 0x000F;	// Retrieve message length.
			CAN_MSG_ID[0] = C1RX1SID >> 5;
			CAN_MSG_ID[1] = C1RX1SID << 3;

			if(CAN_MSG_DLC > 0)
			{
				CAN_MSG_DATA[0] = C1RX1B1 & 0xFF;
				if(CAN_MSG_DLC > 1)
				{
					CAN_MSG_DATA[1] = C1RX1B1 >> 8;
					if(CAN_MSG_DLC > 2)
					{
						CAN_MSG_DATA[2] = C1RX1B2 & 0xFF;
						if(CAN_MSG_DLC > 3)
						{
							CAN_MSG_DATA[3] = C1RX1B2 >> 8;
							if(CAN_MSG_DLC > 4)
							{
								CAN_MSG_DATA[4] = C1RX1B3 & 0xFF;
								if(CAN_MSG_DLC > 5)
								{
									CAN_MSG_DATA[5] = C1RX1B3 >> 8;
									if(CAN_MSG_DLC > 6)
									{
										CAN_MSG_DATA[6] = C1RX1B4 & 0xFF;
										if(CAN_MSG_DLC > 7)
										{
											CAN_MSG_DATA[7] = C1RX1B4 >> 8;
										}
									}
								}
							}
						}
					}
				}
			}
			C1RX1CONbits.RXFUL = 0;
		}
		else
			return 0;
	}

	retval = 1;

#else

	if (buffer == 1)
	{
	   //status_mask = 0x02;       //if using CAN_ReadStatus
	   status_mask = 0x80;         //if using CAN_ReadRXStatus
	} else {
	   //status_mask = 0x01;       //if using CAN_ReadStatus
	   status_mask = 0x40;         //if using CAN_ReadRXStatus
	}

	//rx_status = CAN_ReadStatus();    //if using CAN_ReadStatus
	rx_status = CAN_ReadRXStatus();    //if using CAN_ReadRXStatus

	if ((rx_status & status_mask) != 0)
	{
	   retval = 1;

	   //now read in the id and data info
	   CAN_ReadRX_ID_and_Data(buffer);
	}

#endif

	return (retval);
/*Macro_CheckRx_End*/
}


void ShowLEDs(char led1, char led2)
{
/*Macro_ShowLEDs_Start*/

#ifdef USE_INT_CAN

#else

	// Code_CAN_ShowLEDs
	char data = 0;

	if (led1 != 0)
	{
	   data = data | 0x10;
	}
	if (led2 != 0)
	{
	   data = data | 0x20;
	}

	CAN_BitModify(BFPCTRL, 0x30, data);

#endif

/*Macro_ShowLEDs_End*/
}


char ReadSwitches()
{
/*Macro_ReadSwitches_Start*/

	char retval = 0;

#ifdef USE_INT_CAN

#else

	// Code_CAN_ReadSwitches
	retval = CAN_Read(TXRTSCTRL);

	retval = retval & 0x38;         // mask off the state
	retval = retval / 8;            // divide by 8 to leave switch data in bottom 3 bits

#endif

	return (retval);
/*Macro_ReadSwitches_End*/
}


char GetRxDataCount(char buffer)
{
/*Macro_GetRxDataCount_Start*/

	return (CAN_MSG_DLC);

/*Macro_GetRxDataCount_End*/
}


char GetRxData(char buffer, char index)
{
/*Macro_GetRxData_Start*/

	if (index > 7)
	{
	   return (0);
	}
	return (CAN_MSG_DATA[index]);

/*Macro_GetRxData_End*/
}


void SetTxData(char buffer, char data_cnt, char d0, char d1, char d2, char d3, char d4, char d5, char d6, char d7)
{
/*Macro_SetTxData_Start*/

	// Code_CAN_SetTxData
	if (buffer > CAN_MAX_TX_BUF)
	{
	   return;
	}

	if (data_cnt > 8)
	{
	   return;
	}


#ifdef USE_INT_CAN

	switch(buffer)
	{
		case 0:
			C1TX0DLC = data_cnt << 3;		// TX Buffer 0
			if (data_cnt > 0)
			{
			   C1TX0B1 = d0;
			   if (data_cnt > 1)
			   {
			   	   C1TX0B1 = C1TX0B1 | (d1 << 8);
				   if (data_cnt > 2)
				   {
			   		   C1TX0B2 = d2;
					   if (data_cnt > 3)
					   {
			   	           C1TX0B2 = C1TX0B2 | (d3 << 8);
						   if (data_cnt > 4)
						   {
			   		           C1TX0B3 = d4;
							   if (data_cnt > 5)
							   {
			   	                   C1TX0B3 = C1TX0B3 | (d5 << 8);
								   if (data_cnt > 6)
								   {
			   		                   C1TX0B4 = d6;
									   if (data_cnt > 7)
									   {
			   	                   			C1TX0B4 = C1TX0B4 | (d7 << 8);
									   }
								   }
							   }
						   }
					   }
				   }
			   }
			}
			break;
		case 1:
			C1TX1DLC = data_cnt << 3;		// TX Buffer 1
			if (data_cnt > 0)
			{
			   C1TX1B1 = d0;
			   if (data_cnt > 1)
			   {
			   	   C1TX1B1 = C1TX1B1 | (d1 << 8);
				   if (data_cnt > 2)
				   {
			   		   C1TX1B2 = d2;
					   if (data_cnt > 3)
					   {
			   	           C1TX1B2 = C1TX1B2 | (d3 << 8);
						   if (data_cnt > 4)
						   {
			   		           C1TX1B3 = d4;
							   if (data_cnt > 5)
							   {
			   	                   C1TX1B3 = C1TX1B3 | (d5 << 8);
								   if (data_cnt > 6)
								   {
			   		                   C1TX1B4 = d6;
									   if (data_cnt > 7)
									   {
			   	                   			C1TX1B4 = C1TX1B4 | (d7 << 8);
									   }
								   }
							   }
						   }
					   }
				   }
			   }
			}
			break;
		case 2:
			C1TX2DLC = data_cnt << 3;		// TX Buffer 0
			if (data_cnt > 0)
			{
			   C1TX2B1 = d0;
			   if (data_cnt > 1)
			   {
			   	   C1TX2B1 = C1TX2B1 | (d1 << 8);
				   if (data_cnt > 2)
				   {
			   		   C1TX2B2 = d2;
					   if (data_cnt > 3)
					   {
			   	           C1TX2B2 = C1TX2B2 | (d3 << 8);
						   if (data_cnt > 4)
						   {
			   		           C1TX2B3 = d4;
							   if (data_cnt > 5)
							   {
			   	                   C1TX2B3 = C1TX2B3 | (d5 << 8);
								   if (data_cnt > 6)
								   {
			   		                   C1TX2B4 = d6;
									   if (data_cnt > 7)
									   {
			   	                   			C1TX2B4 = C1TX2B4 | (d7 << 8);
									   }
								   }
							   }
						   }
					   }
				   }
			   }
			}
			break;
	}

#else

	char i;
	char dlc_addr = TXBxDLC(buffer);

	//enable SPI
	clear_bit(MX_CAN_CS_PORT, CAN_CHIPSEL);

	SPI_SendByte(CAN_WRITE);        //CAN write mode
	SPI_SendByte(dlc_addr);         //start writting at address 0x00
	SPI_SendByte(data_cnt);         //send the DLC value

	//now fill the data bytes...
	//if (data_cnt > 0)
	//{
	//  for (i=0; i<data_cnt; i++)
	//  {
	//      SPI_SendByte(CAN_TXMSG[i]);
	//  }
	//}

	//now fill the data bytes...
	if (data_cnt > 0)
	{
	   SPI_SendByte(d0);
	   if (data_cnt > 1)
	   {
		   SPI_SendByte(d1);
		   if (data_cnt > 2)
		   {
			   SPI_SendByte(d2);
			   if (data_cnt > 3)
			   {
				   SPI_SendByte(d3);
				   if (data_cnt > 4)
				   {
					   SPI_SendByte(d4);
					   if (data_cnt > 5)
					   {
						   SPI_SendByte(d5);
						   if (data_cnt > 6)
						   {
							   SPI_SendByte(d6);
							   if (data_cnt > 7)
							   {
								   SPI_SendByte(d7);
							   }
						   }
					   }
				   }
			   }
		   }
	   }
	}

	//disable SPI
	set_bit(MX_CAN_CS_PORT, CAN_CHIPSEL);

#endif

/*Macro_SetTxData_End*/
}


void SetTxID(char buffer, char hi, char lo)
{
/*Macro_SetTxID_Start*/

	// Code_SetTxID
	if (buffer > CAN_MAX_TX_BUF)
	{
	   return;
	}

#ifdef USE_INT_CAN

	switch(buffer)
	{
		case 0:
			C1TX0SID = ((hi << 5) | (lo >> 3)) & 0x00FF;	//Transmit Buffer 0 S-ID
			C1TX0SID = C1TX0SID | ((hi << 8) & 0xFF00);
			break;
		case 1:
			C1TX1SID = ((hi << 5) | (lo >> 3)) & 0x00FF;	//Transmit Buffer 1 S-ID
			C1TX1SID = C1TX1SID | ((hi << 8) & 0xFF00);
			break;
		case 2:
			C1TX2SID = ((hi << 5) | (lo >> 3)) & 0x00FF;	//Transmit Buffer 2 S-ID
			C1TX2SID = C1TX2SID | ((hi << 8) & 0xFF00);
			break;
	}

#else

	char i;
	char id_addr = TXBxSIDH(buffer);

	//enable SPI
	clear_bit(MX_CAN_CS_PORT, CAN_CHIPSEL);

	SPI_SendByte(CAN_WRITE);        //CAN write mode
	SPI_SendByte(id_addr);          //start writting at hi id address
	SPI_SendByte(hi);               //send the Hi ID value
	SPI_SendByte(lo);               //send the Lo ID value

	//disable SPI
	set_bit(MX_CAN_CS_PORT, CAN_CHIPSEL);

#endif

/*Macro_SetTxID_End*/
}


char GetRxIDLo(char buffer)
{
/*Macro_GetRxIDLo_Start*/

	return (CAN_MSG_ID[1]);

/*Macro_GetRxIDLo_End*/
}


char GetRxIDHi(char buffer)
{
/*Macro_GetRxIDHi_Start*/

	return (CAN_MSG_ID[0]);

/*Macro_GetRxIDHi_End*/
}


