/*********************************************************************
 *                Flowcode Switch Bank Component Code
 *
 * File: PIC_SWITCHbank.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
 * -------+----+-----------------------------------------------------
 * 110607 | BR | Created
 * 040707 | ST | Fixes to code
 * 050707 | ST | Added "GetDefines" and optimised code
 * 180309 | BR | Changed delays to be WDT compatible
 * 240309 | BR | Moves private functions from AddDefines
 * 130509 | BR | Added % definitions to DefinesCode section
 * 270110 | BR | Added a method for the 10F to allow the tris to work correctly
 * 011211 | BR | Updated FC_CAL_Bit functions
 * 280212 | BR | Added full debounce support
 * 020312 | BR | Fixed debounce overflow bug and switch polarity issue
 * 100512 | BR | Fixed a bug where the waituntil functions were not working with bits other then 0
 ********************************************************************/

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

 Return & parameter types:
   void
   MX_UINT8
   MX_SINT16
   MX_STRING

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

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

[Settings]
CLSID={708547A8-80AE-45BD-8149-600A4580B1E1}
IsAnalogue=0
MultipleAllowed=1
Description=Switch Bank Flowcode Component

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

NOTE: For simulation to work, these macros _MUST_ remain at the indicated index:
	2=ReadState
	3=WaitUntilHigh
	4=WaitUntilLow


[MacroNames]
Count=4
1=ReadPin
2=ReadState
3=WaitUntilHigh
4=WaitUntilLow

[MacroReturns]
1=MX_UINT8
2=MX_UINT8
3=void
4=void

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


[MacroParameters_ReadPin]
Count=1
1=WhichSwitch

[MacroParamTypes_ReadPin]
1=MX_UINT8

[MacroParameters_ReadState]
Count=1
1=WhichSwitch

[MacroParamTypes_ReadState]
1=MX_UINT8

[MacroParameters_WaitUntilHigh]
Count=1
1=WhichSwitch

[MacroParamTypes_WaitUntilHigh]
1=MX_UINT8

[MacroParameters_WaitUntilLow]
Count=1
1=WhichSwitch

[MacroParamTypes_WaitUntilLow]
1=MX_UINT8

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

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

/*DefinesCode_Start*/

/**** Macro Substitutions ****
a = Unique Reference
b = Switch Port Letter
c = Number of switches
d = Switch Pin 0
e = Switch Pin 1
f = Switch Pin 2
g = Switch Pin 3
h = Switch Pin 4
i = Switch Pin 5
j = Switch Pin 6
k = Switch Pin 7
l = Switch Active Polarity
m = Switch Debounce Delay (us)
******************************/

#define %a_SWITCH_PORT		port%b
#define %a_SWITCH_TRIS		tris%b
#define %a_NUM_SWITCHES		%c
#define %a_SWITCH_PIN_0		%d
#define %a_SWITCH_PIN_1		%e
#define %a_SWITCH_PIN_2		%f
#define %a_SWITCH_PIN_3		%g
#define %a_SWITCH_PIN_4		%h
#define %a_SWITCH_PIN_5		%i
#define %a_SWITCH_PIN_6		%j
#define %a_SWITCH_PIN_7		%k
#define %a_SWITCH_POLE		%l

//Work out a schema for debounce delays
#define %a_SW_DELAY		%m * 90					//80% + overhead
#define %a_SW_DEL		delay_us(10)

#if (%a_SW_DELAY > 65535)
	#undef %a_SW_DELAY
	#undef %a_SW_DEL
	#define %a_SW_DELAY		%m * 9				//80% + overhead
	#define %a_SW_DEL		delay_us(100)
	#if (%a_SW_DELAY > 65535)
		#undef %a_SW_DELAY
		#undef %a_SW_DEL
		#define %a_SW_DELAY		%m
		#define %a_SW_DEL		delay_ms(1)
		#if (%a_SW_DELAY > 65535)
			#error "Switch %a Debounce Delay Too Large."
		#endif
	#endif
#endif

/*DefinesCode_End*/

/*InitialisationCode_Start*/
/*InitialisationCode_End*/

/*InterruptCode_Start*/
/*InterruptCode_End*/

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


MX_UINT8 ReadPin(MX_UINT8 WhichSwitch)
{
/*Macro_ReadPin_Start*/

	MX_UINT8 pinlevel = 0;

	switch (WhichSwitch)
	{
		case 0:
		default:
			FC_CAL_Bit_In_DDR ( %a_SWITCH_PORT, %a_SWITCH_TRIS, %a_SWITCH_PIN_0 );
			pinlevel = FC_CAL_Bit_In ( %a_SWITCH_PORT, %a_SWITCH_PIN_0 );
			break;
	  #if %a_NUM_SWITCHES > 1
		case 1:
			FC_CAL_Bit_In_DDR ( %a_SWITCH_PORT, %a_SWITCH_TRIS, %a_SWITCH_PIN_1 );
			pinlevel = FC_CAL_Bit_In ( %a_SWITCH_PORT, %a_SWITCH_PIN_1 );
			break;
	  #endif
	  #if %a_NUM_SWITCHES > 2
		case 2:
			FC_CAL_Bit_In_DDR ( %a_SWITCH_PORT, %a_SWITCH_TRIS, %a_SWITCH_PIN_2 );
			pinlevel = FC_CAL_Bit_In ( %a_SWITCH_PORT, %a_SWITCH_PIN_2 );
			break;
	  #endif
	  #if %a_NUM_SWITCHES > 3
		case 3:
			FC_CAL_Bit_In_DDR ( %a_SWITCH_PORT, %a_SWITCH_TRIS, %a_SWITCH_PIN_3 );
			pinlevel = FC_CAL_Bit_In ( %a_SWITCH_PORT, %a_SWITCH_PIN_3 );
			break;
	  #endif
	  #if %a_NUM_SWITCHES > 4
		case 4:
			FC_CAL_Bit_In_DDR ( %a_SWITCH_PORT, %a_SWITCH_TRIS, %a_SWITCH_PIN_4 );
			pinlevel = FC_CAL_Bit_In ( %a_SWITCH_PORT, %a_SWITCH_PIN_4 );
			break;
	  #endif
	  #if %a_NUM_SWITCHES > 5
		case 5:
			FC_CAL_Bit_In_DDR ( %a_SWITCH_PORT, %a_SWITCH_TRIS, %a_SWITCH_PIN_5 );
			pinlevel = FC_CAL_Bit_In ( %a_SWITCH_PORT, %a_SWITCH_PIN_5 );
			break;
	  #endif
	  #if %a_NUM_SWITCHES > 6
		case 6:
			FC_CAL_Bit_In_DDR ( %a_SWITCH_PORT, %a_SWITCH_TRIS, %a_SWITCH_PIN_6 );
			pinlevel = FC_CAL_Bit_In ( %a_SWITCH_PORT, %a_SWITCH_PIN_6 );
			break;
	  #endif
	  #if %a_NUM_SWITCHES > 7
		case 7:
			FC_CAL_Bit_In_DDR ( %a_SWITCH_PORT, %a_SWITCH_TRIS, %a_SWITCH_PIN_7 );
			pinlevel = FC_CAL_Bit_In ( %a_SWITCH_PORT, %a_SWITCH_PIN_7 );
			break;
	  #endif
	}

	return (pinlevel);

/*Macro_ReadPin_End*/
}


MX_UINT8 ReadState(MX_UINT8 WhichSwitch)
{
/*Macro_ReadState_Start*/

	MX_UINT8 switchval = 255;

  #if (%a_SW_DELAY > 0)
	MX_UINT16 del_count;
	MX_UINT8 old_switchval;
  #endif

	switchval = ReadPin(WhichSwitch);				//Convert pin to input

  #if (%a_SWITCH_POLE == 0)
	if (pinlevel)									//Invert logic if required
		pinlevel = 0;
	else
		pinlevel = 1;
  #endif

  #if (%a_SW_DELAY > 0)

	del_count = 0;
	old_switchval = 255;

	while (del_count < %a_SW_DELAY)				//Debounce input
	{
		%a_SW_DEL;
		switchval = ReadPin(WhichSwitch);			//Sample input

	  #if (%a_SWITCH_POLE == 0)
		if (pinlevel)									//Invert logic if required
			pinlevel = 0;
		else
			pinlevel = 1;
	  #endif

		if (switchval == old_switchval)				//Is switch the same state?
			del_count++;							//Increment counter
		else
			del_count = 0;							//Else reset counter

		old_switchval = switchval;					//Update the old state
	}
  #endif

	if (switchval)
		return (1);
	else
		return (0);

/*Macro_ReadState_End*/
}


void WaitUntilHigh(MX_UINT8 WhichSwitch)
{
/*Macro_WaitUntilHigh_Start*/

	MX_UINT8 switchval = 255;
	MX_UINT8 temp = %a_SWITCH_POLE << WhichSwitch;

  #if (%a_SW_DELAY > 0)
	MX_UINT16 del_count;
	MX_UINT8 old_switchval;
  #endif

	while (switchval != temp)									//While state not active
	{
		switchval = ReadPin(WhichSwitch);						//Convert pin to input

	  #if (%a_SW_DELAY > 0)

	  	del_count = 0;
	  	old_switchval = 255;

		while (del_count < %a_SW_DELAY)							//Debounce input
		{
			%a_SW_DEL;
			switchval = ReadPin(WhichSwitch);					//Sample input

			if (switchval == old_switchval)						//Is switch the same state?
				del_count++;									//Increment counter
			else
				del_count = 0;									//Else reset counter

			old_switchval = switchval;							//Update the old state
		}
	  #endif

	}

/*Macro_WaitUntilHigh_End*/
}


void WaitUntilLow(MX_UINT8 WhichSwitch)
{
/*Macro_WaitUntilLow_Start*/

	MX_UINT8 temp = %a_SWITCH_POLE << WhichSwitch;
	MX_UINT8 switchval = temp;

  #if (%a_SW_DELAY > 0)
	MX_UINT16 del_count = 0;
	MX_UINT8 old_switchval;
  #endif

	while (switchval == temp)									//While state active
	{
		switchval = ReadPin(WhichSwitch);						//Convert pin to input

	  #if (%a_SW_DELAY > 0)

	  	del_count = 0;
	  	old_switchval = 255;

		while (del_count < %a_SW_DELAY)							//Debounce input
		{
			%a_SW_DEL;
			switchval = ReadPin(WhichSwitch);					//Sample input

			if (switchval == old_switchval)						//Is switch the same state?
				del_count++;									//Increment counter
			else
				del_count = 0;									//Else reset counter

			old_switchval = switchval;							//Update the old state
		}
	  #endif
	}

/*Macro_WaitUntilLow_End*/
}