/*********************************************************************
 *                 Flowcode CAN Component Code
 *
 * File: PIC_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
 * 231109 | SK | Commented out definitions of TX1IE, TX2IE, TX1IF, TX2IF. Clash with definitions for some PIC devices (18F8490).
 *
 ********************************************************************/

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

 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_CAN_BitModify]
Count=1
1=cfg

[MacroParamTypes_CAN_BitModify]
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
******************************/

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

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

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

//////////////////////////////////////////////////////////
//THESE SHOULD *NOT* BE MODIFIED BY THE USER:
/////////////////////////////////////////////////////////
#ifndef MX_SPI
    asm error "Chip does not have SPI capability"
#endif

#ifdef MX_SPI_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_SPI_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_SPI_BCB
  #define MX_CAN_PORT 		portb
  #define MX_CAN_TRIS 		trisb
  #define MX_CAN_SDO_TRIS 	trisc
  #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_MIAC
  #undef MX_CAN_CS_PORT
  #undef MX_CAN_CS_TRIS
  #undef MX_CAN_INT_PORT
  #undef MX_CAN_INT_TRIS
  #undef CAN_CHIPSEL
  #undef CAN_INTERRUPT
  #undef CAN_INT_MASK
  #define MX_CAN_CS_PORT 	portd
  #define MX_CAN_CS_TRIS 	trisd
  #define MX_CAN_INT_PORT 	porta
  #define MX_CAN_INT_TRIS 	trisa
  #define CAN_CHIPSEL  		7
  #define CAN_INTERRUPT  	4
  #define CAN_INT_MASK  	16
#endif

#ifndef MX_CAN_PORT
    asm error "MX_CAN_PORT has not been assigned"
#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

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

#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

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


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

//CANCTRL
#define REQOP_CONFIG		0x80
#define REQOP_LISTEN		0x60
#define REQOP_LOOPBACK		0x40
#define REQOP_SLEEP			0x20
#define REQOP_NORMAL		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))


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


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

char BF_MASK;

char CAN_MSG_DLC;
char CAN_MSG_DATA[8];

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

/*DefinesCode_End*/

/*InitialisationCode_Start*/
/*InitialisationCode_End*/

/*InterruptCode_Start*/
/*InterruptCode_End*/

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

//internal function implementations
void SPI_Init()
{
/*Macro_SPI_Init_Start*/
	#ifndef MX_SPI
		asm error "Chip does not have SPI capability"
	#endif

	//initialise spi
	set_bit(MX_CAN_TRIS,MX_SPI_SDI);
	clear_bit(MX_CAN_SDO_TRIS,MX_SPI_SDO);
	clear_bit(MX_CAN_TRIS,MX_SPI_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);

	sspstat = 0;
	set_bit(sspstat, CKE);		//SMP = 0, CKE = 1

	#ifdef SSPCON
		sspcon = 0;					//CKP = 0 and SPI master Fosc/4
		set_bit(sspcon, SSPEN);		//Enable SPI
	#endif
	#ifdef SSPCON1
		sspcon1 = 0;				//CKP = 0 and SPI master Fosc/4
		set_bit(sspcon1, SSPEN);	//Enable SPI
	#endif

	//get the mask for the BF bit for later use
	BF_MASK = CAN_MaskFromBit(BF);
/*Macro_SPI_Init_End*/
}


char SPI_SendByte(char byte)
{
/*Macro_SPI_SendByte_Start*/
	char retval = 0;

	//send the byte
	sspbuf = byte;

	//wait until data has been received (transmit complete)
	while ((sspstat & BF_MASK) == 0);

	//get received byte
	retval = sspbuf;

	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 MX_SPI
	asm error "Chip does not have SPI capability"
  #endif

	//enable SPI
	clear_bit(MX_CAN_CS_PORT, CAN_CHIPSEL);

	sspbuf = CAN_RESET;					//send the reset byte
	while ((sspstat & BF_MASK) == 0);	//wait until data has been received (transmit complete)

	//disable SPI
	set_bit(MX_CAN_CS_PORT, CAN_CHIPSEL);

	//wait for the CAN device to complete its OST
	//Wdt_Delay_Ms(1);	//10us is ok, but us delay cannot be created by boostc linker
	delay_10us(2);
/*Macro_CAN_Reset_End*/
}


void CAN_Write(char addr, char data)
{
/*Macro_CAN_Write_Start*/
  #ifndef MX_SPI
	asm error "Chip does not have SPI capability"
  #endif

	//enable SPI
	clear_bit(MX_CAN_CS_PORT, CAN_CHIPSEL);

	sspbuf = CAN_WRITE;					//send a byte
	while ((sspstat & BF_MASK) == 0);	//wait until data has been received (transmit complete)
	sspbuf = addr;						//send the address
	while ((sspstat & BF_MASK) == 0);	//wait until data has been received (transmit complete)
	sspbuf = data;						//send the data
	while ((sspstat & BF_MASK) == 0);	//wait until data has been received (transmit complete)

	//disable SPI
	set_bit(MX_CAN_CS_PORT, CAN_CHIPSEL);
/*Macro_CAN_Write_End*/
}


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

  #ifndef MX_SPI
	asm error "Chip does not have SPI capability"
  #endif

	//enable SPI
	clear_bit(MX_CAN_CS_PORT, CAN_CHIPSEL);

	sspbuf = CAN_READ;					//read a byte
	while ((sspstat & BF_MASK) == 0);	//wait until data has been received (transmit complete)
	sspbuf = addr	;					//send the address
	while ((sspstat & BF_MASK) == 0);	//wait until data has been received (transmit complete)
	sspbuf = 0x5A	;					//send a don't care byte
	while ((sspstat & BF_MASK) == 0);	//wait until data has been received (transmit complete)
	data = sspbuf;						//read back the result

	//disable SPI
	set_bit(MX_CAN_CS_PORT, CAN_CHIPSEL);

	return (data);
/*Macro_CAN_Read_End*/
}


void CAN_Config(char cfg)
{
/*Macro_CAN_Config_Start*/
	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
/*Macro_CAN_Config_End*/
}


char CAN_ReadStatus()
{
/*Macro_CAN_ReadStatus_Start*/
	char retval = 0;

	#ifndef MX_SPI
		asm error "Chip does not have SPI capability"
	#endif

	//enable SPI
	clear_bit(MX_CAN_CS_PORT, CAN_CHIPSEL);

	sspbuf = CAN_RD_STATUS;				//read the status
	while ((sspstat & BF_MASK) == 0);	//wait until data has been received (transmit complete)
	sspbuf = 0x5A;						//send a don't care byte
	while ((sspstat & BF_MASK) == 0);	//wait until data has been received (transmit complete)
	retval = sspbuf;					//read back the result

	//disable SPI
	set_bit(MX_CAN_CS_PORT, CAN_CHIPSEL);

	return (retval);
/*Macro_CAN_ReadStatus_End*/
}


char CAN_ReadRXStatus()
{
/*Macro_CAN_ReadRXStatus_Start*/
	char retval = 0;

	#ifndef MX_SPI
		asm error "Chip does not have SPI capability"
	#endif

	//enable SPI
	clear_bit(MX_CAN_CS_PORT, CAN_CHIPSEL);

	sspbuf = CAN_RX_STATUS;				//read the status
	while ((sspstat & BF_MASK) == 0);	//wait until data has been received (transmit complete)
	sspbuf = 0x5A;						//send a don't care byte
	while ((sspstat & BF_MASK) == 0);	//wait until data has been received (transmit complete)
	retval = sspbuf;					//read back the result

	//disable SPI
	set_bit(MX_CAN_CS_PORT, CAN_CHIPSEL);

	return (retval);
/*Macro_CAN_ReadRXStatus_End*/
}


void CAN_BitModify(char addr, char mask, char data)
{
/*Macro_CAN_BitModify_Start*/
	#ifndef MX_SPI
		asm error "Chip does not have SPI capability"
	#endif

	//enable SPI
	clear_bit(MX_CAN_CS_PORT, CAN_CHIPSEL);

	sspbuf = CAN_BIT_MODIFY;			//bit modify
	while ((sspstat & BF_MASK) == 0);	//wait until data has been received (transmit complete)
	sspbuf = addr;						//send the address
	while ((sspstat & BF_MASK) == 0);	//wait until data has been received (transmit complete)
	sspbuf = mask;						//send the mask
	while ((sspstat & BF_MASK) == 0);	//wait until data has been received (transmit complete)
	sspbuf = data;						//send the data
	while ((sspstat & BF_MASK) == 0);	//wait until data has been received (transmit complete)

	//disable SPI
	set_bit(MX_CAN_CS_PORT, CAN_CHIPSEL);
/*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 MX_SPI
	asm error "Chip does not have SPI capability"
  #endif

	//enable SPI
	clear_bit(MX_CAN_CS_PORT, CAN_CHIPSEL);

	sspbuf = CAN_RD_RXBUF_ID(buffer);	//read the RX ID
	while ((sspstat & BF_MASK) == 0);	//wait until data has been received (transmit complete)

	sspbuf = 0x5A;						//send a don't care byte
	while ((sspstat & BF_MASK) == 0);	//wait until data has been received (transmit complete)
	CAN_MSG_ID[idx++] = sspbuf;			//read back SIDH

	sspbuf = 0x5A;						//send a don't care byte
	while ((sspstat & BF_MASK) == 0);	//wait until data has been received (transmit complete)
	CAN_MSG_ID[idx++] = sspbuf;			//read back SIDL

	sspbuf = 0x5A;						//send a don't care byte
	while ((sspstat & BF_MASK) == 0);	//wait until data has been received (transmit complete)
  #ifdef CAN_USE_EXID
	CAN_MSG_ID[idx++] = sspbuf;			//read back EXID8
  #endif

	sspbuf = 0x5A;						//send a don't care byte
	while ((sspstat & BF_MASK) == 0);	//wait until data has been received (transmit complete)
  #ifdef CAN_USE_EXID
	CAN_MSG_ID[idx++] = sspbuf;			//read back EXID0
  #endif

	sspbuf = 0x5A;						//send a don't care byte
	while ((sspstat & BF_MASK) == 0);	//wait until data has been received (transmit complete)
	CAN_MSG_DLC = sspbuf;				//read back DLC

	//now read the data (if there is any)
	if (CAN_MSG_DLC > 0)
	{
		sspbuf = 0x5A;						//send a don't care byte
		while ((sspstat & BF_MASK) == 0);	//wait until data has been received (transmit complete)
		CAN_MSG_DATA[0] = sspbuf;			//read back D0

		if (CAN_MSG_DLC > 1)
		{
			sspbuf = 0x5A;						//send a don't care byte
			while ((sspstat & BF_MASK) == 0);	//wait until data has been received (transmit complete)
			CAN_MSG_DATA[1] = sspbuf;			//read back D1


			if (CAN_MSG_DLC > 2)
			{
				sspbuf = 0x5A;						//send a don't care byte
				while ((sspstat & BF_MASK) == 0);	//wait until data has been received (transmit complete)
				CAN_MSG_DATA[2] = sspbuf;			//read back D2

				if (CAN_MSG_DLC > 3)
				{
					sspbuf = 0x5A;						//send a don't care byte
					while ((sspstat & BF_MASK) == 0);	//wait until data has been received (transmit complete)
					CAN_MSG_DATA[3] = sspbuf;			//read back D3

					if (CAN_MSG_DLC > 4)
					{
						sspbuf = 0x5A;						//send a don't care byte
						while ((sspstat & BF_MASK) == 0);	//wait until data has been received (transmit complete)
						CAN_MSG_DATA[4] = sspbuf;			//read back D4

						if (CAN_MSG_DLC > 5)
						{
							sspbuf = 0x5A;						//send a don't care byte
							while ((sspstat & BF_MASK) == 0);	//wait until data has been received (transmit complete)
							CAN_MSG_DATA[5] = sspbuf;			//read back D5

							if (CAN_MSG_DLC > 6)
							{
								sspbuf = 0x5A;						//send a don't care byte
								while ((sspstat & BF_MASK) == 0);	//wait until data has been received (transmit complete)
								CAN_MSG_DATA[6] = sspbuf;			//read back D6

								if (CAN_MSG_DLC > 7)
								{
									sspbuf = 0x5A;						//send a don't care byte
									while ((sspstat & BF_MASK) == 0);	//wait until data has been received (transmit complete)
									CAN_MSG_DATA[7] = sspbuf;			//read back D7

								}
							}
						}
					}
				}
			}
		}
	}


	//disable SPI
	set_bit(MX_CAN_CS_PORT, CAN_CHIPSEL);

	return (CAN_MSG_DLC);
/*Macro_CAN_ReadRX_ID_and_Data_End*/
}


void Init()
{
/*Macro_Init_Start*/
	//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);
/*Macro_Init_End*/
}


void SendBuffer(char buffer)
{
/*Macro_SendBuffer_Start*/
	// Code_CAN_SendBuffer
	if (buffer > CAN_MAX_TX_BUF)
	{
	   return;
	}

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

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

	//enable SPI
	clear_bit(MX_CAN_CS_PORT, CAN_CHIPSEL);

	sspbuf = cmd;                       //send the RTS command
	while ((sspstat & BF_MASK) == 0);   //wait until data has been received (transmit complete)

	//disable SPI
	set_bit(MX_CAN_CS_PORT, CAN_CHIPSEL);
/*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_TX_BUF)
	{
	   return (0);
	}

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

	return (retval);
/*Macro_CheckRx_End*/
}


void ShowLEDs(char led1, char led2)
{
/*Macro_ShowLEDs_Start*/
	// Code_CAN_ShowLEDs
	char data = 0;

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

	CAN_BitModify(BFPCTRL, 0x30, data);
/*Macro_ShowLEDs_End*/
}


char ReadSwitches()
{
/*Macro_ReadSwitches_Start*/
	// Code_CAN_ReadSwitches
	char 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

	return (retval);
/*Macro_ReadSwitches_End*/
}


char GetRxDataCount(char buffer)
{
/*Macro_GetRxDataCount_Start*/
	// Code_CAN_GetRxDataCount
	if (buffer > CAN_MAX_TX_BUF)
	{
	   return (0);
	}

	return (CAN_MSG_DLC);
/*Macro_GetRxDataCount_End*/
}


char GetRxData(char buffer, char index)
{
/*Macro_GetRxData_Start*/
	// Code_CAN_GetRxData
	if (buffer > CAN_MAX_TX_BUF)
	{
	   return (0);
	}
	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;
	}

	char i;
	char dlc_addr = TXBxDLC(buffer);

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

	//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);
/*Macro_SetTxData_End*/
}


void SetTxID(char buffer, char hi, char lo)
{
/*Macro_SetTxID_Start*/
	// Code_SetTxID
	if (buffer > CAN_MAX_TX_BUF)
	{
	   return;
	}

	char i;
	char id_addr = TXBxSIDH(buffer);

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

	//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);
/*Macro_SetTxID_End*/
}


char GetRxIDLo(char buffer)
{
/*Macro_GetRxIDLo_Start*/
	// Code_CAN_GetRxIDLo
	if (buffer > CAN_MAX_TX_BUF)
	{
	   return (0);
	}

	return (CAN_MSG_ID[1]);
/*Macro_GetRxIDLo_End*/
}


char GetRxIDHi(char buffer)
{
/*Macro_GetRxIDHi_Start*/
	// Code_CAN_GetRxIDHi
	if (buffer > CAN_MAX_TX_BUF)
	{
	   return (0);
	}

	return (CAN_MSG_ID[0]);
/*Macro_GetRxIDHi_End*/
}