/*********************************************************************
 *              Flowcode Quaderature Encoder Component Code
 *
 * File: QuaderatureEncoder.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
 * -------+----+-----------------------------------------------------
 * 241111 | BR | Created
 * 011211 | BR | Updated FC_CAL_Bit functions
 ********************************************************************/

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

 Return & parameter types:
   void
   MX_UINT8
   MX_SINT16
   MX_STRING

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

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

[Settings]
IsAnalogue=0
MultipleAllowed=1
Description=Quaderature Encoder Flowcode Component

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

NOTE: For simulation to work, these macros _MUST_ remain at the indicated index:
	1=Enable
	2=Disable
	3=Check_For_Changes
	4=Read_Counter
	5=Reset_Counter

[MacroNames]
Count=5
1=Enable
2=Disable
3=Check_For_Changes
4=Read_Counter
5=Reset_Counter

[MacroReturns]
1=void
2=void
3=char
4=short
5=void

[MacroIsPrivate]
1=0
2=0
3=0
4=0
5=0

[MacroParameters_Enable]
Count=0

[MacroParamTypes_Enable]


[MacroParameters_Disable]
Count=0

[MacroParamTypes_Disable]


[MacroParameters_Check_For_Changes]
Count=0

[MacroParamTypes_Check_For_Changes]


[MacroParameters_Read_Counter]
Count=0

[MacroParamTypes_Read_Counter]


[MacroParameters_Reset_Counter]
Count=0

[MacroParamTypes_Reset_Counter]

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

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

/*DefinesCode_Start*/

/**** Macro Substitutions ****
a = Unique Reference
b = Encoder Pin A Port Letter
c = Encoder Pin A Pin Number
d = Encoder Pin B Port Letter
e = Encoder Pin B Pin Number
******************************/

#define 	%a_ENC_PORT_A		port%b
#define 	%a_ENC_TRIS_A		tris%b
#define 	%a_ENC_PIN_A		%c
#define 	%a_ENC_PORT_B		port%d
#define 	%a_ENC_TRIS_B		tris%d
#define 	%a_ENC_PIN_B		%e

char 	%a_encoder_en = 0;
char 	%a_encoder_mask = 0;
short 	%a_encoder_count = 0;


/*DefinesCode_End*/

/*InitialisationCode_Start*/

	set_bit( %a_ENC_TRIS_A, %a_ENC_PIN_A );
	set_bit( %a_ENC_TRIS_B, %a_ENC_PIN_B );

/*InitialisationCode_End*/

/*InterruptCode_Start*/
/*InterruptCode_End*/

/********************************************************************
 * PROTOTYPES
 ********************************************************************/

void 		Enable();
void 		Disable();
char		Check_For_Changes();
short		Read_Counter();
void 		Reset_Counter();

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

void Enable()
{
/*Macro_Enable_Start*/

	%a_encoder_en = 1;
	%a_encoder_mask = 0;

	//Collectt initial encoder input readings

	if ( test_bit( %a_ENC_PORT_A , %a_ENC_PIN_A ) )
		%a_encoder_mask = %a_encoder_mask | 0x01;

	if ( test_bit( %a_ENC_PORT_B , %a_ENC_PIN_B ) )
		%a_encoder_mask = %a_encoder_mask | 0x02;

/*Macro_Enable_End*/
}

void Disable()
{
/*Macro_Disable_Start*/

	%a_encoder_en = 0;

/*Macro_Disable_End*/
}

MX_UINT8 Check_For_Changes()
{
/*Macro_Check_For_Changes_Start*/

	char maskcheck = 0;

	if (%a_encoder_en)
	{
		if ( test_bit( %a_ENC_PORT_A , %a_ENC_PIN_A ) )	//Read A Input
			maskcheck = maskcheck | 0x01;

		if ( test_bit( %a_ENC_PORT_B , %a_ENC_PIN_B ) )	//Read B Input
			maskcheck = maskcheck | 0x02;

		if (maskcheck == %a_encoder_mask)						//No movement detected
			return 0;

		if (maskcheck == (~%a_encoder_mask & 0x03))				//Two steps detected - Data corrupted
			return 255;

		//If we get here then a valid encoder state change has been detected

		switch (maskcheck)										//Search for current state
		{
			case ( 0 ):
				if ( %a_encoder_mask == 2 )
					%a_encoder_count = %a_encoder_count + 1;
				else
					%a_encoder_count = %a_encoder_count - 1;
				break;

			case ( 1 ):
				if ( %a_encoder_mask == 0 )
					%a_encoder_count = %a_encoder_count + 1;
				else
					%a_encoder_count = %a_encoder_count - 1;
				break;

			case ( 3 ):
				if ( %a_encoder_mask == 1 )
					%a_encoder_count = %a_encoder_count + 1;
				else
					%a_encoder_count = %a_encoder_count - 1;
				break;

			case ( 2 ):
				if ( %a_encoder_mask == 3 )
					%a_encoder_count = %a_encoder_count + 1;
				else
					%a_encoder_count = %a_encoder_count - 1;
				break;
		}

		%a_encoder_mask = maskcheck;		//Reset encoder mask for next operation
		return 1;
	}
	return 0;

/*Macro_Check_For_Changes_End*/
}

MX_SINT16 Read_Counter()
{
/*Macro_Read_Counter_Start*/

	return %a_encoder_count;				//Return count value

/*Macro_Read_Counter_End*/
}

void Reset_Counter()
{
/*Macro_Reset_Counter_Start*/

	%a_encoder_count = 0;					//Reset count value

/*Macro_Reset_Counter_End*/
}
