/*********************************************************************
 *                    Flowcode Accelerometer Component Code
 *
 * File: Accelerometer.c
 *
 * (c) 2011 Matrix Multimedia Ltd.
 * http://www.matrixmultimedia.com
 *
 * Software License Agreement
 *
 * The software supplied herewith by Matrix Multimedia Ltd (the
 * “Company”) for its Flowcode graphical programming language is
 * intended and supplied to you, the Company’s customer, for use
 * solely and exclusively on the Company's products. The software
 * is owned by the Company, and is protected under applicable
 * copyright laws. All rights are reserved. Any use in violation
 * of the foregoing restrictions may subject the user to criminal
 * sanctions under applicable laws, as well as to civil liability
 * for the breach of the terms and conditions of this licence.
 *
 * THIS SOFTWARE IS PROVIDED IN AN “AS IS” CONDITION. NO WARRANTIES,
 * WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
 * TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
 * IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
 * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
 *
 * Changelog:
 *
 *  date  | by | description
 * -------+----+-----------------------------------------------------
 * 090211 | BR | Created
 * 230311 | BR | Updated error messages to allow BoostC or HiTech
 * 281011 | BR | Converted to Universal Accelerometer Component Code File
 * 041111 | ST | Added MOSI and CS pins
 * 011211 | BR | Updated FC_CAL_Bit functions
 * 021211 | BR | Converted to new dynamic defines mechanism
 * 230412 | BR | Removed unused variables
 ********************************************************************/

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

 Return & parameter types:
   void
   MX_UINT8
   MX_SINT16
   MX_STRING

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


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

[Settings]
CLSID={4B174520-75AB-4B14-A0F7-2AA6C203F1DC}
IsAnalogue=0
MultipleAllowed=1
Description=Flowcode Accelerometer Component

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

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

[Pins]
Count=6
1=Data Available
2=Power
3=SDA / SDI
4=SCL / SCK
5=N/A / SDO
6=N/A / CS

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

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

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

[PinMustUsePort]
# boolean
1=0
2=0
3=0
4=0
5=0
6=0

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

[PinMustUsePin]
# boolean
1=1
2=1
3=1
4=1
5=0
6=0

[PinValue]
# boolean (0 = off, 1 = on)
1=0
2=0
3=0
4=0
5=0
6=0

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

[MacroNames]
Count=9
1=Initialise
2=Update_XYZ_Data
3=Collect_XYZ_Data
4=Write_Register
5=Write_N_Registers
6=Read_Register
7=Read_N_Registers
8=init_transaction
9=end_transaction

[MacroReturns]
1=MX_UINT8
2=MX_UINT8
3=MX_SINT16
4=MX_UINT8
5=void
6=MX_UINT8
7=void
8=MX_UINT8
9=void

[MacroIsPrivate]
1=0
2=0
3=0
4=1
5=1
6=1
7=1
8=1
9=1

[MacroParameters_Initialise]
Count=0

[MacroParamTypes_Initialise]

[MacroParameters_Update_XYZ_Data]
Count=0

[MacroParamTypes_Update_XYZ_Data]

[MacroParameters_Collect_XYZ_Data]
Count=1
1=axis

[MacroParamTypes_Collect_XYZ_Data]
1=MX_UINT8

[MacroParameters_Write_Register]
Count=2
1=reg
2=data

[MacroParamTypes_Write_Register]
1=MX_UINT8
2=MX_UINT8

[MacroParameters_Write_N_Registers]
Count=3
1=start_reg
2=num_regs
3=data

[MacroParamTypes_Write_N_Registers]
1=MX_UINT8
2=MX_UINT8
3=MX_STRING

[MacroParameters_Read_Register]
Count=1
1=reg

[MacroParamTypes_Read_Register]
1=MX_UINT8

[MacroParameters_Read_N_Registers]
Count=3
1=start_reg
2=num_regs
3=ret_data

[MacroParamTypes_Read_N_Registers]
1=MX_UINT8
2=MX_UINT8
3=MX_STRING

[MacroParameters_init_transaction]
Count=3
1=mode
2=reg
3=multiple

[MacroParamTypes_init_transaction]
1=MX_UINT8
2=MX_UINT8
3=MX_UINT8

[MacroParameters_end_transaction]
Count=0

[MacroParamTypes_end_transaction]


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

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


/*DefinesCode_Start*/

/**** Macro Substitutions ****
a = Unique component ID
b = I2C/SPI Channel - 0=SW, 1-4=HW
c = I2C/SPI - 0=SPI 1=I2C
d = SDA/MISO Port
e = SDA/MISO Pin
f = SCL/SCK Port
g = SCL/SCK Pin
h = MOSI Port
i = MOSI Pin
j = CS Port
k = CS Pin
l = INT Port
m = INT Pin
n = PWR Port
o = PWR Pin
p = Accelerometer Data Rate - 0=40hz, 1=160hz, 2=640hz, 3=2560hz
q = Accelerometer Data Scale - 0=+/-2G, 1=+/-6G
******************************/

//ACCELEROMETER COMPONENT DEFINES
#define %a_BUS				%c				//0=SPI, 1=I2C
#define %a_DATA_RATE		%p				//0=40hz, 1=160hz, 2=640hz, 3=2560hz
#define %a_SCALE			%q				//0=+/-2G, 1=+/-6G
#define %a_ADDRESS			0x3A			//Default address 0x3A

#define %a_INT_PIN			%m
#define %a_INT_PORT			port%l
#define %a_INT_TRIS			tris%l
#define %a_PWR_PIN			%o
#define %a_PWR_PORT			port%n
#define %a_PWR_TRIS			tris%n

#if (%a_BUS == 0)							//SPI COMPONENT DEFINES

	#define %a_CS_PIN 		%k
	#define %a_CS_PORT		port%j
	#define %a_CS_TRIS		tris%j

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

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

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

#else												//I2C COMPONENT DEFINES

	//Definitions for I2C slot allocation
	#ifndef	MX_I2C_REF1
		#define MX_I2C_REF1
		#define %a_MX_I2C_UREF			1
		#define MX_I2C_CHANNEL_1		%b
		#define MX_I2C_SDA_PIN_1		%e
		#define MX_I2C_SDA_PORT_1		port%d
		#define MX_I2C_SDA_TRIS_1		tris%d
		#define MX_I2C_SCL_PIN_1		%g
		#define MX_I2C_SCL_PORT_1		port%f
		#define MX_I2C_SCL_TRIS_1		tris%f
		#define MX_I2C_BMODE_1			0
		#define MX_I2C_BAUD_1			60
		#define MX_I2C_INT_1			0
	#else
	 #ifndef MX_I2C_REF2
		#define MX_I2C_REF2
		#define %a_MX_I2C_UREF			2
		#define MX_I2C_CHANNEL_2		%b
		#define MX_I2C_SDA_PIN_2		%e
		#define MX_I2C_SDA_PORT_2		port%d
		#define MX_I2C_SDA_TRIS_2		tris%d
		#define MX_I2C_SCL_PIN_2		%g
		#define MX_I2C_SCL_PORT_2		port%f
		#define MX_I2C_SCL_TRIS_2		tris%f
		#define MX_I2C_BMODE_2			0
		#define MX_I2C_BAUD_2			60
		#define MX_I2C_INT_2			0
	 #else
	  #ifndef MX_I2C_REF3
		#define MX_I2C_REF3
		#define %a_MX_I2C_UREF			3
		#define MX_I2C_CHANNEL_3		%b
		#define MX_I2C_SDA_PIN_3		%e
		#define MX_I2C_SDA_PORT_3		port%d
		#define MX_I2C_SDA_TRIS_3		tris%d
		#define MX_I2C_SCL_PIN_3		%g
		#define MX_I2C_SCL_PORT_3		port%f
		#define MX_I2C_SCL_TRIS_3		tris%f
		#define MX_I2C_BMODE_3			0
		#define MX_I2C_BAUD_3			60
		#define MX_I2C_INT_3			0
	  #else
	   #ifndef MX_I2C_REF4
		#define MX_I2C_REF4
		#define %a_MX_I2C_UREF			4
		#define MX_I2C_CHANNEL_4		%b
		#define MX_I2C_SDA_PIN_4		%e
		#define MX_I2C_SDA_PORT_4		port%d
		#define MX_I2C_SDA_TRIS_4		tris%d
		#define MX_I2C_SCL_PIN_4		%g
		#define MX_I2C_SCL_PORT_4		port%f
		#define MX_I2C_SCL_TRIS_4		tris%f
		#define MX_I2C_BMODE_4			0
		#define MX_I2C_BAUD_4			60
		#define MX_I2C_INT_4			0
	   #endif
	  #endif
	 #endif
	#endif

	#define %a_I2C_Master_Init		CAL_APPEND(FC_CAL_I2C_Master_Init_, %a_MX_I2C_UREF)
	#define %a_I2C_Master_Uninit	CAL_APPEND(FC_CAL_I2C_Master_Uninit_, %a_MX_I2C_UREF)
	#define %a_I2C_Master_Start		CAL_APPEND(FC_CAL_I2C_Master_Start_, %a_MX_I2C_UREF)
	#define %a_I2C_Master_Restart	CAL_APPEND(FC_CAL_I2C_Master_Restart_, %a_MX_I2C_UREF)
	#define %a_I2C_Master_Stop		CAL_APPEND(FC_CAL_I2C_Master_Stop_, %a_MX_I2C_UREF)
	#define %a_I2C_Master_TX_Byte	CAL_APPEND(FC_CAL_I2C_Master_TX_Byte_, %a_MX_I2C_UREF)
	#define %a_I2C_Master_RX_Byte	CAL_APPEND(FC_CAL_I2C_Master_RX_Byte_, %a_MX_I2C_UREF)

	extern void %a_I2C_Master_Init ();
	extern void %a_I2C_Master_Uninit ();
	extern void %a_I2C_Master_Start ();
	extern void %a_I2C_Master_Restart ();
	extern void %a_I2C_Master_Stop ();
	extern MX_UINT8 %a_I2C_Master_TX_Byte (MX_UINT8 Data);
	extern MX_UINT8 %a_I2C_Master_RX_Byte (MX_UINT8 Last);

#endif

//global variables
MX_SINT16 %a_MX_X_Var = 0;
MX_SINT16 %a_MX_Y_Var = 0;
MX_SINT16 %a_MX_Z_Var = 0;

/*DefinesCode_End*/

/*InitialisationCode_Start*/
/*InitialisationCode_End*/

/*InterruptCode_Start*/
/*InterruptCode_End*/


MX_UINT8 Initialise(void)
{
/*Macro_Initialise_Start*/

	MX_UINT8 temp_reg = 0xC7;
	MX_UINT8 RetVal;

	FC_CAL_Bit_High_DDR(%a_PWR_PORT, %a_PWR_TRIS, %a_PWR_PIN);			//Switch on device
	delay_ms(100);														//Wait for power up

	FC_CAL_Bit_In_DDR(%a_INT_PORT, %a_INT_TRIS, %a_INT_PIN);

	#if (%a_BUS == 0)
		FC_CAL_Bit_High_DDR(%a_CS_PORT, %a_CS_TRIS, %a_CS_PIN);			//Configure and disable chip select
		%a_SPI_Master_Init ();
	#else
		%a_I2C_Master_Init ();
	#endif

	temp_reg = temp_reg | (%a_DATA_RATE << 4);
	RetVal = Write_Register(0x20, temp_reg);							//startup device

	if (RetVal)
		return 255;

	temp_reg = %a_SCALE << 7;
	temp_reg = temp_reg | 0x44;
	RetVal = Write_Register(0x21, temp_reg);							//scale selection

	if (RetVal)
		return 254;

	return 0;

/*Macro_Initialise_End*/
}


MX_UINT8 Update_XYZ_Data(void)
{
/*Macro_Update_XYZ_Data_Start*/

	if( FC_CAL_Bit_In( %a_INT_PORT , %a_INT_PIN ) )
	{
		%a_MX_X_Var = Read_Register(0x28);
		%a_MX_X_Var = %a_MX_X_Var | ( Read_Register(0x29) << 8);
		%a_MX_Y_Var = Read_Register(0x2A);
		%a_MX_Y_Var = %a_MX_Y_Var | ( Read_Register(0x2B) << 8);
		%a_MX_Z_Var = Read_Register(0x2C);
		%a_MX_Z_Var = %a_MX_Z_Var | ( Read_Register(0x2D) << 8);

		return 1;
	}
	else
		return 0;
/*Macro_Update_XYZ_Data_End*/
}


MX_SINT16 Collect_XYZ_Data(MX_UINT8 axis)
{
/*Macro_Collect_XYZ_Data_Start*/
	switch(axis)
	{
		case 0:
		case 'x':
		case 'X':
			return %a_MX_X_Var;
		case 1:
		case 'y':
		case 'Y':
			return %a_MX_Y_Var;
		case 2:
		case 'z':
		case 'Z':
			return %a_MX_Z_Var;
	}
	return -1;
/*Macro_Collect_XYZ_Data_End*/
}


void Write_Register(MX_UINT8 reg, MX_UINT8 data)
{
/*Macro_Write_Register_Start*/

	MX_UINT8 RetVal;

	RetVal = init_transaction(0, reg, 0);								//Start Transaction

	if (RetVal)
		return 255;

	#if (%a_BUS == 0)													//SPI TRANSACTION
		%a_SPI_Master_Byte(data);
	#else																//I2C TRANSACTION
		RetVal = %a_I2C_Master_TX_Byte(data);
	#endif

	end_transaction();													//End Transaction

	return RetVal;

/*Macro_Write_Register_End*/
}


void Write_N_Registers(MX_UINT8 start_reg, MX_UINT8 num_regs, MX_STRING data)
{
/*Macro_Write_N_Registers_Start*/

	MX_UINT8 i;
	MX_UINT8 j = 0;
	init_transaction(0, start_reg, 1);
	for(i=start_reg; i<(start_reg + num_regs); i++)
	{
		#if (%a_BUS == 0)												//SPI TRANSACTION
			%a_SPI_Master_Byte(data[j]);
		#else															//I2C TRANSACTION
			%a_I2C_Master_TX_Byte(data[j]);
		#endif
		j = j + 1;
	}
	end_transaction();

/*Macro_Write_N_Registers_End*/
}


MX_UINT8 Read_Register(MX_UINT8 reg)
{
/*Macro_Read_Register_Start*/

	MX_UINT8 Retval;
	init_transaction(1, reg, 0);

	#if (%a_BUS == 0)													//SPI TRANSACTION
		Retval = %a_SPI_Master_Byte(0x55);
	#else																//I2C TRANSACTION
		Retval = %a_I2C_Master_RX_Byte(1);
	#endif

	end_transaction();
	return Retval;

/*Macro_Read_Register_End*/
}


void Read_N_Registers(MX_UINT8 start_reg, MX_UINT8 num_regs, MX_STRING ret_data)
{
/*Macro_Read_N_Registers_Start*/

	MX_UINT8 i;
	MX_UINT8 j = 0;
	MX_UINT8 last = 0;
	init_transaction(1, start_reg, 1);
	for(i=start_reg; i<(start_reg+num_regs); i++)
	{
		#if (%a_BUS == 0)												//SPI TRANSACTION
			ret_data[j] = %a_SPI_Master_Byte(0x55);
		#else															//I2C TRANSACTION
			if(j == (num_regs - 1))
				last = 1;
			ret_data[j] = %a_I2C_Master_RX_Byte(last);
		#endif
		j = j + 1;
	}
	end_transaction();

/*Macro_Read_N_Registers_End*/
}


MX_UINT8 init_transaction(MX_UINT8 mode, MX_UINT8 reg, MX_UINT8 multiple)
{
/*Macro_init_transaction_Start*/

	MX_UINT8 temp_addr;
	MX_UINT8 ack = 1;

	#if (%a_BUS == 0)									//SPI TRANSACTION

		FC_CAL_Bit_Low(%a_CS_PORT, %a_CS_PIN);

		if(multiple)
			reg = reg | 0x40;
		if (mode)
			reg = reg | 0x01;

		%a_SPI_Master_Byte(reg);
		return 0;

	#else												//I2C TRANSACTION

		%a_I2C_Master_Start();							//Start I2C
		%a_I2C_Master_TX_Byte(%a_ADDRESS);		//Send address and read / write command

		if(multiple)
			reg = reg | 0x80;

		ack = %a_I2C_Master_TX_Byte(reg);			//Send register and single / multiple command
		if (ack)
			return 255;

		if (mode)
		{
			temp_addr = %a_ADDRESS | 0x01;							//Calculate address and read / write command
			%a_I2C_Master_Restart();
			ack = %a_I2C_Master_TX_Byte(temp_addr);
		}
		return ack;
	#endif

/*Macro_init_transaction_End*/
}


void end_transaction()
{
/*Macro_end_transaction_Start*/

	#if (%a_BUS == 0)									//SPI TRANSACTION
		FC_CAL_Bit_High(%a_CS_PORT, %a_CS_PIN);
	#else												//I2C TRANSACTION
		%a_I2C_Master_Stop();
	#endif

/*Macro_end_transaction_End*/
}















