/*********************************************************************
 *                    Flowcode Keypad Component Code
 *
 * File: Keypad_Code.c
 *
 * (c) 2007 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
 * -------+----+-----------------------------------------------------
 * 080509 | LM | Modified to inverse the logic levels: 1 = OFF 0 = ON
 *        |    | and to inverse the i/o of port: 
 *        |    |     rows = outputs, columns = inputs
 * 240407 | ST | Created
 *        |    |
 *        |    |
 *        |    |
 *        |    |
 *
 *
 *
 ********************************************************************/

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

 Return & parameter types:
   void
   char
   short
   char*

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

 Macro substitutions:
	%a = key list (numbers)
	%b = key list (chars)
	%c = tris
	%d = port
	%e = col count
	%f = row count
	%g =
	%h =
	%i = column1 mask
	%j = column2 mask
	%k = column3 mask
	%l = column4 mask
	%m = row1 mask
	%n = row2 mask
	%o = row3 mask
	%p = row4 mask

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

[Settings]
CLSID={EAF84433-ACA7-4AD5-A512-A21E01997A15}
IsAnalogue=0
MultipleAllowed=0
Description=Keypad Flowcode Component

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

[Port]
DesiredPort=0
PortMandatory=0
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

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

[PinMustUsePin]
# boolean

[PinValue]
# boolean (1 = off, 0 = on)

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

[MacroNames]
Count=2
1=GetKeypadNumber
2=GetKeypadAscii

[MacroReturns]
1=char
2=char

[MacroIsPrivate]
1=0
2=0


[MacroParameters_GetKeypadNumber]
Count=0

[MacroParamTypes_GetKeypadNumber]


[MacroParameters_GetKeypadAscii]
Count=0

[MacroParamTypes_GetKeypadAscii]


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

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

/*InitialisationCode_Start*/
/*InitialisationCode_End*/

/*InterruptCode_Start*/
/*InterruptCode_End*/


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


char GetKeypadNumber()
{
/*Macro_GetKeypadNumber_Start*/
	//get matrices for rows and columns
	#if (%e == 1)
		#define KPAD_COL_MTX {%i}
		#define KPAD_COL_MASK (%i)
	#endif
	#if (%e == 2)
		#define KPAD_COL_MTX {%i,%j}
		#define KPAD_COL_MASK (%i|%j)
	#endif
	#if (%e == 3)
		#define KPAD_COL_MTX {%i,%j,%k}
		#define KPAD_COL_MASK (%i|%j|%k)
	#endif
	#if (%e == 4)
		#define KPAD_COL_MTX {%i,%j,%k,%l}
		#define KPAD_COL_MASK (%i|%j|%k|%l)
	#endif
	#if (%f == 1)
		#define KPAD_ROW_MTX {%m}
		#define KPAD_ROW_MASK (%m)
	#endif
	#if (%f == 2)
		#define KPAD_ROW_MTX {%m,%n}
		#define KPAD_ROW_MASK (%m|%n)
	#endif
	#if (%f == 3)
		#define KPAD_ROW_MTX {%m,%n,%o}
		#define KPAD_ROW_MASK (%m|%n|%o)
	#endif
	#if (%f == 4)
		#define KPAD_ROW_MTX {%m,%n,%o,%p}
		#define KPAD_ROW_MASK (%m|%n|%o|%p)
	#endif

	#ifndef KPAD_COL_MTX
		#pragma error Keypad error: column count is not 1-4
	#endif
	#ifndef KPAD_ROW_MTX
		#pragma error Keypad error: row count is not 1-4
	#endif

	//store keys and pin connections into a constant array
	rom char* mtxKeysAsNumbers = %a;
	rom char* mtxCols = KPAD_COL_MTX;
	rom char* mtxRows = KPAD_ROW_MTX;

	//set up i/o of port (rows = outputs, columns = inputs)
	%c = (%c | KPAD_COL_MASK) & ~KPAD_ROW_MASK;

	char iCol;
	char iRow;
	char c_ip;
	for (iRow=1; iRow<%f; iRow++)
	{
		//output the appropriate row high
		%d = mtxRows[iRow];

		//delay
		nop();nop();nop();nop();
		nop();nop();nop();nop();
		nop();nop();nop();nop();

		//read the port
		c_ip = %d;

		//check for a hit
		for (iCol=1; iCol<%e; iCol++)
		{
			if ((c_ip & mtxCols[iCol]) != 1)
			{
				//found it!
				goto found_key;
			}
		}
	}

	//if it gets here, it has not been found...
	return (255);

  found_key:
	return (mtxKeysAsNumbers[(iRow*%e) + iCol]);

  #undef KPAD_COL_MTX
  #undef KPAD_ROW_MTX
  #undef KPAD_COL_MASK
  #undef KPAD_ROW_MASK

/*Macro_GetKeypadNumber_End*/
}


char GetKeypadAscii()
{
/*Macro_GetKeypadAscii_Start*/
	//get matrices for rows and columns
	#if (%e == 1)
		#define KPAD_COL_MTX {%i}
		#define KPAD_COL_MASK (%i)
	#endif
	#if (%e == 2)
		#define KPAD_COL_MTX {%i,%j}
		#define KPAD_COL_MASK (%i|%j)
	#endif
	#if (%e == 3)
		#define KPAD_COL_MTX {%i,%j,%k}
		#define KPAD_COL_MASK (%i|%j|%k)
	#endif
	#if (%e == 4)
		#define KPAD_COL_MTX {%i,%j,%k,%l}
		#define KPAD_COL_MASK (%i|%j|%k|%l)
	#endif
	#if (%f == 1)
		#define KPAD_ROW_MTX {%m}
		#define KPAD_ROW_MASK (%m)
	#endif
	#if (%f == 2)
		#define KPAD_ROW_MTX {%m,%n}
		#define KPAD_ROW_MASK (%m|%n)
	#endif
	#if (%f == 3)
		#define KPAD_ROW_MTX {%m,%n,%o}
		#define KPAD_ROW_MASK (%m|%n|%o)
	#endif
	#if (%f == 4)
		#define KPAD_ROW_MTX {%m,%n,%o,%p}
		#define KPAD_ROW_MASK (%m|%n|%o|%p)
	#endif

	#ifndef KPAD_COL_MTX
		#pragma error Keypad error: column count is not 1-4
	#endif
	#ifndef KPAD_ROW_MTX
		#pragma error Keypad error: row count is not 1-4
	#endif

	//store keys and pin connections into a constant array
	rom char* mtxKeysAsChars = %b;
	rom char* mtxCols = KPAD_COL_MTX;
	rom char* mtxRows = KPAD_ROW_MTX;

	//set up i/o of port (rows = inputs, columns = outputs)
	%c = (%c | KPAD_COL_MASK) & ~KPAD_ROW_MASK;

	char iCol;
	char iRow;
	char c_ip;
	for (iRow=1; iRow<%f; iRow++)
	{
		//output the appropriate row high
		%d = mtxRows[iRow];

		//delay
		nop();nop();nop();nop();
		nop();nop();nop();nop();
		nop();nop();nop();nop();

		//read the port
		c_ip = %d;

		//check for a hit
		for (iCol=1; iCol<%e; iCol++)
		{
			if ((c_ip & mtxCols[iCol]) != 1)
			{
				//found it!
				goto found_key;
			}
		}
	}

	//if it gets here, it has not been found...
	return (255);

  found_key:
	return (mtxKeysAsChars[(iRow*%e) + iCol]);

  #undef KPAD_COL_MTX
  #undef KPAD_ROW_MTX
  #undef KPAD_COL_MASK
  #undef KPAD_ROW_MASK

/*Macro_GetKeypadAscii_End*/
}

