/*********************************************************************
 *                 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
 * 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
 * 230311 | BR | Changed code to work for hitech and boostc without ifdefs
 * 111111 | ST | Added 4 pins
 * 011211 | BR | Updated FC_CAL_Bit functions
 * 021211 | BR | Converted to new dynamic defines mechanism
 * 190312 | BR | Reduced SPI prescale from 4 to 64 to allow 20MHz AVR to work
 * 020412 | BR | Minor ARM related bug fix
 * 180412 | BR | BF mask was removed as not being used
 * 300512 | ST | Reinstated SPI_SendByte (redundant) to allow simulation in VNET
 ********************************************************************/

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

 Return & parameter types:
   void
   MX_UINT8
   MX_SINT16
   MX_STRING

 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=4
1=Chip Select
2=SDO
3=SDI
4=SCK

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

[PinDesiredBit]
1=0
2=0
3=0
4=0

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

[PinMustUsePort]
# MX_UINT8
1=1
2=1
3=1
4=1

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

[PinMustUsePin]
# MX_UINT8
1=1
2=1
3=1
4=1

[PinValue]
# MX_UINT8 (0 = off, 1 = on)
1=0
2=0
3=0
4=0

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

NOTE: For simulation to work, these macros _MUST_ remain at the indicated index:
	13=SendBuffer
	14=CheckRx
	17=GetRxDataCount
	18=GetRxData
	19=SetTxData
	20=SetTxID
	21=GetRxIDLo
	22=GetRxIDHi


[MacroNames]
Count=24
1=SPI_Init
2=SPI_SendByte_Redundant
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
23=SetRxFiltrID
24=SetRxMaskID

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

[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
23=0
24=0


[MacroParameters_SPI_Init]
Count=0

[MacroParamTypes_SPI_Init]

[MacroParameters_SPI_SendByte_Redundant]
Count=0

[MacroParamTypes_SPI_SendByte_Redundant]

[MacroParameters_CAN_MaskFromBit]
Count=1
1=which_bit

[MacroParamTypes_CAN_MaskFromBit]
1=MX_UINT8

[MacroParameters_CAN_Reset]
Count=0

[MacroParamTypes_CAN_Reset]


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

[MacroParamTypes_CAN_Write]
1=MX_UINT8
2=MX_UINT8

[MacroParameters_CAN_Read]
Count=1
1=addr

[MacroParamTypes_CAN_Read]
1=MX_UINT8


[MacroParameters_CAN_Config]
Count=1
1=cfg

[MacroParamTypes_CAN_Config]
1=MX_UINT8


[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=MX_UINT8
2=MX_UINT8
3=MX_UINT8

[MacroParameters_CAN_ReadRX_ID_and_Data]
Count=1
1=buffer

[MacroParamTypes_CAN_ReadRX_ID_and_Data]
1=MX_UINT8

[MacroParameters_Init]
Count=0

[MacroParamTypes_Init]


[MacroParameters_SendBuffer]
Count=1
1=buffer

[MacroParamTypes_SendBuffer]
1=MX_UINT8

[MacroParameters_CheckRx]
Count=1
1=buffer

[MacroParamTypes_CheckRx]
1=MX_UINT8

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

[MacroParamTypes_ShowLEDs]
1=MX_UINT8
2=MX_UINT8

[MacroParameters_ReadSwitches]
Count=0

[MacroParamTypes_ReadSwitches]


[MacroParameters_GetRxDataCount]
Count=1
1=buffer

[MacroParamTypes_GetRxDataCount]
1=MX_UINT8

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

[MacroParamTypes_GetRxData]
1=MX_UINT8
2=MX_UINT8

[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=MX_UINT8
2=MX_UINT8
3=MX_UINT8
4=MX_UINT8
5=MX_UINT8
6=MX_UINT8
7=MX_UINT8
8=MX_UINT8
9=MX_UINT8
10=MX_UINT8

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

[MacroParamTypes_SetTxID]
1=MX_UINT8
2=MX_UINT8
3=MX_UINT8

[MacroParameters_GetRxIDLo]
Count=1
1=buffer

[MacroParamTypes_GetRxIDLo]
1=MX_UINT8

[MacroParameters_GetRxIDHi]
Count=1
1=buffer

[MacroParamTypes_GetRxIDHi]
1=MX_UINT8

[MacroParameters_SetRxFiltrID]
Count=3
1=filter
2=hi
3=lo

[MacroParamTypes_SetRxFiltrID]
1=MX_UINT8
2=MX_UINT8
3=MX_UINT8

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

[MacroParamTypes_SetRxMaskID]
1=MX_UINT8
2=MX_UINT8
3=MX_UINT8

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

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

/*DefinesCode_Start*/

/**** Macro Substitutions ****

//Global Component
a = Unique Ref
b = Internal CAN enable - 0=SPI, 1=INTCAN
c = Transmit Buffer 0 Messages
d = Transmit Buffer 1 Messages
e = Transmit Buffer 2 Messages
f = Receive Buffer 0 Messages
g = Receive Buffer 1 Messages
h = Bit Rate0
i = Bit Rate1
j = Bit Rate2

//SPI CAN
k = SPI Channel - 0=SW, >0=HW
l = MOSI Pin
m = MOSI Port
n = MISO Pin
o = MISO Port
p = SCK Pin
q = SCK Port
r = Clock Polarity + Clock Phase + Data Sample Phase
s = SPI Prescaler
t = SPI Postscaler
u = CAN Enable Pin
v = CAN Enable Port
w = Buffer Control
x = TXRTS Control

//Internal CAN
y = Internal CAN Channel - 1/2=HW no SW mode available
******************************/

//Common defines
#define INTERNAL_CAN_ENABLE		%b

//Transmission messages (TXB0-2):
%c
%d
%e

//Reception (TXB0-1)
%f
%g

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

//One shot mode, CLKOUT enable, CLKOUT prescaler
#define CANCTRL_VAL		0x80
#define 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		0x80
#define REQOP_LISTEN		0x60
#define REQOP_LOOPBACK		0x40
#define REQOP_SLEEP			0x20
#define REQOP_NORMAL		0x00

MX_UINT8 CAN_MSG_DLC;
MX_UINT8 CAN_MSG_DATA[8];
MX_UINT8 MsgFlags = 0;
//MX_UINT8 BF_MASK;

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

#if INTERNAL_CAN_ENABLE == 1

	#define %a_USE_INT_CAN

	//Definitions for CAN slot allocation
	#ifndef	MX_CAN_REF1
		#define MX_CAN_REF1
		#define %a_MX_CAN_UREF			1
		#define MX_CAN_CHANNEL_1		%y
		#define MX_CAN_BAUD1_1			%h
		#define MX_CAN_BAUD2_1			%i
		#define MX_CAN_BAUD3_1			%j
	#else
	 #ifndef MX_CAN_REF2
		#define MX_CAN_REF2
		#define %a_MX_CAN_UREF			2
		#define MX_CAN_CHANNEL_2		%y
		#define MX_CAN_BAUD1_2			%h
		#define MX_CAN_BAUD2_2			%i
		#define MX_CAN_BAUD3_2			%j
	 #endif
	#endif

	#define %a_Internal_CAN_Init				CAL_APPEND(FC_CAL_Internal_CAN_Init_, %a_MX_CAN_UREF)
	#define %a_Internal_CAN_Uninit				CAL_APPEND(FC_CAL_Internal_CAN_Uninit_, %a_MX_CAN_UREF)
	#define %a_Internal_CAN_Send_Buffer			CAL_APPEND(FC_CAL_Internal_CAN_Send_Buffer_, %a_MX_CAN_UREF)
	#define %a_Internal_CAN_CheckRX				CAL_APPEND(FC_CAL_Internal_CAN_CheckRX_, %a_MX_CAN_UREF)
	#define %a_Internal_CAN_Set_TX_Data			CAL_APPEND(FC_CAL_Internal_CAN_Set_TX_Data_, %a_MX_CAN_UREF)
	#define %a_Internal_CAN_Set_TX_Std_ID		CAL_APPEND(FC_CAL_Internal_CAN_Set_TX_Std_ID_, %a_MX_CAN_UREF)
	#define %a_Internal_CAN_Set_TX_Exd_ID		CAL_APPEND(FC_CAL_Internal_CAN_Set_TX_Exd_ID_, %a_MX_CAN_UREF)
	#define %a_Internal_CAN_Set_Std_RX_Filter	CAL_APPEND(FC_CAL_Internal_CAN_Set_Std_RX_Filter_, %a_MX_CAN_UREF)
	#define %a_Internal_CAN_Set_Exd_RX_Filter	CAL_APPEND(FC_CAL_Internal_CAN_Set_Exd_RX_Filter_, %a_MX_CAN_UREF)
	#define %a_Internal_CAN_Set_Std_RX_Mask		CAL_APPEND(FC_CAL_Internal_CAN_Set_Std_RX_Mask_, %a_MX_CAN_UREF)
	#define %a_Internal_CAN_Set_Exd_RX_Mask		CAL_APPEND(FC_CAL_Internal_CAN_Set_Exd_RX_Mask, %a_MX_CAN_UREF)

	extern void %a_Internal_CAN_Init();
	extern void %a_Internal_CAN_Uninit();
	extern void %a_Internal_CAN_Send_Buffer(MX_UINT8 buffer);
	extern MX_UINT8 %a_Internal_CAN_CheckRX(MX_UINT8 buffer);
	extern void %a_Internal_CAN_Set_TX_Data(MX_UINT8 buffer, MX_UINT8 data_cnt, MX_UINT8 d0, MX_UINT8 d1, MX_UINT8 d2, MX_UINT8 d3, MX_UINT8 d4, MX_UINT8 d5, MX_UINT8 d6, MX_UINT8 d7);
	extern void %a_Internal_CAN_Set_TX_Std_ID(MX_UINT8 buffer, MX_UINT8 hi, MX_UINT8 lo);
	extern void %a_Internal_CAN_Set_TX_Exd_ID(MX_UINT8 buffer, MX_UINT8 id3, MX_UINT8 id2, MX_UINT8 id1, MX_UINT8 id0);
	extern void %a_Internal_CAN_Set_Std_RX_Filter(MX_UINT8 filter, MX_UINT8 hi, MX_UINT8 lo);
	extern void %a_Internal_CAN_Set_Exd_RX_Filter(MX_UINT8 filter, MX_UINT8 id3, MX_UINT8 id2, MX_UINT8 id1, MX_UINT8 id0);
	extern void %a_Internal_CAN_Set_Std_RX_Mask(MX_UINT8 filter, MX_UINT8 hi, MX_UINT8 lo);
	extern void %a_Internal_CAN_Set_Exd_RX_Mask(MX_UINT8 filter, MX_UINT8 id3, MX_UINT8 id2, MX_UINT8 id1, MX_UINT8 id0);

#else

	//CAN Baud Rate
	#define CNF1_VAL  				%h
	#define CNF2_VAL  				%i
	#define CNF3_VAL  				%j

	//SPI Buffer and Control Variables
	#define BFPCTRL_VAL    			%w
	#define TXRTSCTRL_VAL			%x

	//Definitions for CS control lines
	#define %a_MX_CAN_CS_PIN		%u
	#define %a_MX_CAN_CS_PORT		port%v
	#define %a_MX_CAN_CS_TRIS		tris%v

	//hardcode if using the MIAC
	#ifdef MX_MIAC
	  #undef %a_MX_CAN_CS_PIN
	  #undef %a_MX_CAN_CS_PORT
	  #undef %a_MX_CAN_CS_TRIS
	  #define %a_MX_CAN_CS_PIN		7
	  #define %a_MX_CAN_CS_PORT		portd
	  #define %a_MX_CAN_CS_TRIS		trisd
	#endif

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

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

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

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

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


/*DefinesCode_End*/

/*InitialisationCode_Start*/
/*InitialisationCode_End*/

/*InterruptCode_Start*/
/*InterruptCode_End*/

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

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

  #ifndef %a_USE_INT_CAN

	//Disable SPI CAN Device
	FC_CAL_Bit_High_DDR(%a_MX_CAN_CS_PORT, %a_MX_CAN_CS_TRIS, %a_MX_CAN_CS_PIN);

	//Init SPI
	%a_SPI_Master_Init();		//Call initialise function

	//get the mask for the BF bit for later use
	//#ifdef FC_CAL_ARM
	//	BF_MASK = AT91C_SPI_TXEMPTY;
	//#else
	//	BF_MASK = CAN_MaskFromBit(BF);
	//#endif

  #endif

/*Macro_SPI_Init_End*/
}

void SPI_SendByte_Redundant()
{
/*Macro_SPI_SendByte_Redundant_Start*/

/*Macro_SPI_SendByte_Redundant_End*/
}

MX_UINT8 CAN_MaskFromBit(MX_UINT8 which_bit)
{
/*Macro_CAN_MaskFromBit_Start*/
	MX_UINT8 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 %a_USE_INT_CAN

	//enable SPI
	FC_CAL_Bit_Low_DDR(%a_MX_CAN_CS_PORT, %a_MX_CAN_CS_TRIS, %a_MX_CAN_CS_PIN);

	%a_SPI_Master_Byte(CAN_RESET);

	//disable SPI
	FC_CAL_Bit_High_DDR(%a_MX_CAN_CS_PORT, %a_MX_CAN_CS_TRIS, %a_MX_CAN_CS_PIN);

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

  #endif

/*Macro_CAN_Reset_End*/
}


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

  #ifndef %a_USE_INT_CAN

	//enable SPI
	FC_CAL_Bit_Low_DDR(%a_MX_CAN_CS_PORT, %a_MX_CAN_CS_TRIS, %a_MX_CAN_CS_PIN);

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

	//disable SPI
	FC_CAL_Bit_High_DDR(%a_MX_CAN_CS_PORT, %a_MX_CAN_CS_TRIS, %a_MX_CAN_CS_PIN);

  #endif

/*Macro_CAN_Write_End*/
}


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

	MX_UINT8 data = 0;

  #ifndef %a_USE_INT_CAN

	//enable SPI
	FC_CAL_Bit_Low_DDR(%a_MX_CAN_CS_PORT, %a_MX_CAN_CS_TRIS, %a_MX_CAN_CS_PIN);

	%a_SPI_Master_Byte(CAN_READ);			//read a byte
	%a_SPI_Master_Byte(addr);				//send the address
	data = %a_SPI_Master_Byte(0x5A);		//collect the data

	//disable SPI
	FC_CAL_Bit_High_DDR(%a_MX_CAN_CS_PORT, %a_MX_CAN_CS_TRIS, %a_MX_CAN_CS_PIN);

  #endif

	return (data);

/*Macro_CAN_Read_End*/
}


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

  #ifndef %a_USE_INT_CAN

	MX_UINT8 mode;
	MX_UINT8 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*/
}


MX_UINT8 CAN_ReadStatus()
{
/*Macro_CAN_ReadStatus_Start*/

	MX_UINT8 retval = 0;

  #ifndef %a_USE_INT_CAN

	//enable SPI
	FC_CAL_Bit_Low_DDR(%a_MX_CAN_CS_PORT, %a_MX_CAN_CS_TRIS, %a_MX_CAN_CS_PIN);

	%a_SPI_Master_Byte(CAN_RD_STATUS);		//Read the status
	retval = %a_SPI_Master_Byte(0x5A);		//Collect the data

	//disable SPI
	FC_CAL_Bit_High_DDR(%a_MX_CAN_CS_PORT, %a_MX_CAN_CS_TRIS, %a_MX_CAN_CS_PIN);

  #endif

	return (retval);

/*Macro_CAN_ReadStatus_End*/
}


MX_UINT8 CAN_ReadRXStatus()
{
/*Macro_CAN_ReadRXStatus_Start*/

	MX_UINT8 retval = 0;

  #ifndef %a_USE_INT_CAN

	//enable SPI
	FC_CAL_Bit_Low_DDR(%a_MX_CAN_CS_PORT, %a_MX_CAN_CS_TRIS, %a_MX_CAN_CS_PIN);

	%a_SPI_Master_Byte(CAN_RX_STATUS);		//Read the status
	retval = %a_SPI_Master_Byte(0x5A);		//Collect the data

	//disable SPI
	FC_CAL_Bit_High_DDR(%a_MX_CAN_CS_PORT, %a_MX_CAN_CS_TRIS, %a_MX_CAN_CS_PIN);

  #endif

	return (retval);

/*Macro_CAN_ReadRXStatus_End*/
}


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

  #ifndef %a_USE_INT_CAN

	//enable SPI
	FC_CAL_Bit_Low_DDR(%a_MX_CAN_CS_PORT, %a_MX_CAN_CS_TRIS, %a_MX_CAN_CS_PIN);

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

	//disable SPI
	FC_CAL_Bit_High_DDR(%a_MX_CAN_CS_PORT, %a_MX_CAN_CS_TRIS, %a_MX_CAN_CS_PIN);

  #endif

/*Macro_CAN_BitModify_End*/
}


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

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

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

	#ifndef %a_USE_INT_CAN

		//enable SPI
		FC_CAL_Bit_Low_DDR(%a_MX_CAN_CS_PORT, %a_MX_CAN_CS_TRIS, %a_MX_CAN_CS_PIN);

		%a_SPI_Master_Byte(CAN_RD_RXBUF_ID(buffer));		//read the RX ID

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

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

	  	#ifdef CAN_USE_EXID
			CAN_MSG_ID[idx++] = %a_SPI_Master_Byte(0x5A);		//read back EXID8
	  	#else
	  		%a_SPI_Master_Byte(0x5A);		//send a don't care byte
	  	#endif

	  	#ifdef CAN_USE_EXID
			CAN_MSG_ID[idx++] = %a_SPI_Master_Byte(0x5A);		//read back EXID0
	  	#else
	  		%a_SPI_Master_Byte(0x5A);		//send a don't care byte
	  	#endif

		CAN_MSG_DLC = %a_SPI_Master_Byte(0x5A);			//read back DLC

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

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

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

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

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

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

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

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

		//disable SPI
		FC_CAL_Bit_High_DDR(%a_MX_CAN_CS_PORT, %a_MX_CAN_CS_TRIS, %a_MX_CAN_CS_PIN);

	#endif

	return (CAN_MSG_DLC);
/*Macro_CAN_ReadRX_ID_and_Data_End*/
}


void Init()
{
/*Macro_Init_Start*/

  #ifdef %a_USE_INT_CAN

	%a_Internal_CAN_Init();

  #else

	SPI_Init ();						//Init SPI

	//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
	FC_CAL_Bit_Low_DDR(%a_MX_CAN_CS_PORT, %a_MX_CAN_CS_TRIS, %a_MX_CAN_CS_PIN);		//enable SPI

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

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

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

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

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

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

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

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

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

	FC_CAL_Bit_High_DDR(%a_MX_CAN_CS_PORT, %a_MX_CAN_CS_TRIS, %a_MX_CAN_CS_PIN);		//disable SPI

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

  #endif

/*Macro_Init_End*/
}


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

	if (buffer > CAN_MAX_TX_BUF)
	   return;

  #ifdef %a_USE_INT_CAN

	%a_Internal_CAN_Send_Buffer(buffer);

  #else

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

	FC_CAL_Bit_Low_DDR(%a_MX_CAN_CS_PORT, %a_MX_CAN_CS_TRIS, %a_MX_CAN_CS_PIN);		//enable SPI

	%a_SPI_Master_Byte(cmd);

	FC_CAL_Bit_High_DDR(%a_MX_CAN_CS_PORT, %a_MX_CAN_CS_TRIS, %a_MX_CAN_CS_PIN);		//disable SPI

  #endif

/*Macro_SendBuffer_End*/
}


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

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

	if (buffer > CAN_MAX_RX_BUF)
	   return (0);

  #ifdef %a_USE_INT_CAN

	retval = %a_Internal_CAN_CheckRX(buffer);

  #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(MX_UINT8 led1, MX_UINT8 led2)
{
/*Macro_ShowLEDs_Start*/

  #ifndef %a_USE_INT_CAN

	MX_UINT8 data = 0;

	if (led1 != 0)
	{
	   data = data | 0x10;
	}
	if (led2 != 0)
	{
	   data = data | 0x20;
	}
	CAN_BitModify(BFPCTRL, 0x30, data);

  #endif

/*Macro_ShowLEDs_End*/
}


MX_UINT8 ReadSwitches()
{
/*Macro_ReadSwitches_Start*/

	MX_UINT8 retval = 0;

  #ifndef %a_USE_INT_CAN

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


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

	if (buffer > CAN_MAX_TX_BUF)
	   return (0);

	//**********************************
	return (CAN_MSG_DLC);			//Note MSG DLC may be overwritten by incoming buffer - needs tying to buffer param or dropping buffer param altogether
	//**********************************

/*Macro_GetRxDataCount_End*/
}


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

	if (buffer > CAN_MAX_TX_BUF)
	   return (0);

	if (index > 7)
	   return (0);

	//**********************************
	return (CAN_MSG_DATA[index]);	//Note MSG DLC may be overwritten by incoming buffer - needs tying to buffer param or dropping buffer param altogether
	//**********************************

/*Macro_GetRxData_End*/
}


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

	if (buffer > CAN_MAX_TX_BUF)
  		return;

	if (data_cnt > 8)
	   return;

  #ifdef %a_USE_INT_CAN

	%a_Internal_CAN_Set_TX_Data(buffer, data_cnt, d0, d1, d2, d3, d4, d5, d6, d7);

  #else

	MX_UINT8 i;
	MX_UINT8 dlc_addr = TXBxDLC(buffer);

	FC_CAL_Bit_Low_DDR(%a_MX_CAN_CS_PORT, %a_MX_CAN_CS_TRIS, %a_MX_CAN_CS_PIN);	//enable SPI

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

	//now fill the data bytes...
	if (data_cnt > 0)
	{
	   %a_SPI_Master_Byte(d0);
	   if (data_cnt > 1)
	   {
		   %a_SPI_Master_Byte(d1);
		   if (data_cnt > 2)
		   {
			   %a_SPI_Master_Byte(d2);
			   if (data_cnt > 3)
			   {
				   %a_SPI_Master_Byte(d3);
				   if (data_cnt > 4)
				   {
					   %a_SPI_Master_Byte(d4);
					   if (data_cnt > 5)
					   {
						   %a_SPI_Master_Byte(d5);
						   if (data_cnt > 6)
						   {
							   %a_SPI_Master_Byte(d6);
							   if (data_cnt > 7)
							   {
								   %a_SPI_Master_Byte(d7);
							   }
						   }
					   }
				   }
			   }
		   }
	   }
	}
	FC_CAL_Bit_High_DDR(%a_MX_CAN_CS_PORT, %a_MX_CAN_CS_TRIS, %a_MX_CAN_CS_PIN);	//Disable SPI

  #endif

/*Macro_SetTxData_End*/
}


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

	if (buffer > CAN_MAX_TX_BUF)
	   return;

  #ifdef %a_USE_INT_CAN

	%a_Internal_CAN_Set_TX_Std_ID(buffer, hi, lo);

  #else

	MX_UINT8 id_addr = TXBxSIDH(buffer);

	FC_CAL_Bit_Low_DDR(%a_MX_CAN_CS_PORT, %a_MX_CAN_CS_TRIS, %a_MX_CAN_CS_PIN);	//enable SPI

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

	FC_CAL_Bit_High_DDR(%a_MX_CAN_CS_PORT, %a_MX_CAN_CS_TRIS, %a_MX_CAN_CS_PIN);	//Disable SPI

  #endif

/*Macro_SetTxID_End*/
}


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

	return (CAN_MSG_ID[1]);

/*Macro_GetRxIDLo_End*/
}


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

	return (CAN_MSG_ID[0]);

/*Macro_GetRxIDHi_End*/
}


void SetRxFiltrID (MX_UINT8 filter, MX_UINT8 hi, MX_UINT8 lo)
{
/*Macro_SetRxFiltrID_Start*/

    MX_UINT8 id_addr;

    if (filter > CAN_MAX_RX_BUF)        // modif   D.F
       return;

  #ifdef %a_USE_INT_CAN

	%a_Internal_CAN_Set_Std_RX_Filter(filter, hi, lo);

  #else

    // gestion des 2 banques de RXF
    if (filter < 3)
    {
        id_addr = RXFxaSIDH(filter);        // ŕ tester  modif   D.F
    }
    else
    {
        id_addr = RXFxbSIDH(filter);
    }

    CAN_Config(REQOP_CONFIG);    // necessary for filters (and masks)   D.F

    FC_CAL_Bit_Low_DDR(%a_MX_CAN_CS_PORT, %a_MX_CAN_CS_TRIS, %a_MX_CAN_CS_PIN);	//enable SPI

    %a_SPI_Master_Byte(CAN_WRITE);     	//CAN write mode
    %a_SPI_Master_Byte(id_addr);          //start writting at hi id address
    %a_SPI_Master_Byte(hi);             	//send the SIDH value
    %a_SPI_Master_Byte(lo);             	//send the SIDL value
    %a_SPI_Master_Byte(0xFF);             //send the EID8 value
    %a_SPI_Master_Byte(0xFF);             //send the EID0 value

    FC_CAL_Bit_High_DDR(%a_MX_CAN_CS_PORT, %a_MX_CAN_CS_TRIS, %a_MX_CAN_CS_PIN);	//Disable SPI

    CAN_Config(REQOP_NORMAL);    // close config   D.F

  #endif

/*Macro_SetRxFiltrID_End*/
}


void SetRxMaskID (MX_UINT8 buffer, MX_UINT8 hi, MX_UINT8 lo)
{
/*Macro_SetRxMaskID_Start*/

    if (buffer > CAN_MAX_RX_BUF)        // modif   D.F
    {
       return;
    }

  #ifdef %a_USE_INT_CAN

	%a_Internal_CAN_Set_Std_RX_Mask(buffer, hi, lo);

  #else

    MX_UINT8 id_addr = RXMxSIDH(buffer);     // modif   D.F

    CAN_Config(REQOP_CONFIG);    // necessary for masks   D.F

    FC_CAL_Bit_Low_DDR(%a_MX_CAN_CS_PORT, %a_MX_CAN_CS_TRIS, %a_MX_CAN_CS_PIN);	//enable SPI

    %a_SPI_Master_Byte(CAN_WRITE);        //CAN write mode
    %a_SPI_Master_Byte(id_addr);          //start writting at hi id address
    %a_SPI_Master_Byte(hi);             	//send the SIDH value
    %a_SPI_Master_Byte(lo);             	//send the SIDL value
    %a_SPI_Master_Byte(0xFF);             //send the EID8 value
    %a_SPI_Master_Byte(0xFF);             //send the EID0 value

    FC_CAL_Bit_High_DDR(%a_MX_CAN_CS_PORT, %a_MX_CAN_CS_TRIS, %a_MX_CAN_CS_PIN);	//Disable SPI

    CAN_Config(REQOP_NORMAL);    // close config   D.F

  #endif

/*Macro_SetRxMaskID_End*/
}

