/**********************************************/
/*  ©2006 Spatula Tzar
/*  www.spatulatzar.com
/**********************************************/

#define CODE1 2			/* 4 digits of correct code */
#define CODE2 4
#define CODE3 8
#define CODE4 6
#define VALID 0x10		/* mask for port A<4> */
#define IDLE_TENTHS 30	/* number of tenths of second before reset */

char data;
char data_read;
char digits;
char digit1;
char digit2;
char digit3;
char digit4;
char idle;

main()
{
#asm
	; Configure Ports A<4-0> as input
	movlw	0x1f
	tris	PORTA
	; Configure Port B<7-0> as output
	movlw	0
	tris	PORTB
	movlw	0x20
	movwf	PORTB
#endasm

	delay_sec(1);		/* wait a second before processing data */
	idle      = 0;
	digits    = 0;
	data_read = 0;
	while (1)
	{
		data = RdPortA();
		if (data & VALID)
		{					/* if valid line set */
			idle = 0;
			if (data_read == 0)
			{			/* if digit not processed yet */
				data &= 0xf;
				if (data == 12)
				{			/* if # key */
					if (digits == 4 &&		/* check code */
						digit1 == CODE1 &&
						digit2 == CODE2 &&
						digit3 == CODE3 &&
						digit4 == CODE4)
					{
						WrPortB(0x10);		/* set B<4> if correct code */
						delay_sec(2);
					}

					WrPortB(0x0);			/* reset */
					digits = 0;
					data_read = 0;
				}
				else
				{
					digits++;				/* save the digit */
					data_read = 1;
					if (digits == 1)
					{
						digit1 = data;
					}
					else if (digits == 2)
					{
						digit2 = data;
					}
					else if (digits == 3)
					{
						digit3 = data;
					}
					else if (digits == 4)
					{
						digit4 = data;
					}
				}
			}
		}
		else
		{
			data_read = 0;				/* prepare for next digit */
			idle++;
			if (idle > IDLE_TENTHS)
			{	/* reset if idle too long */
				digits = 0;
				WrPortB(0x0);
			}
		}
		delay_ms(100);
	}
}
/* read IO port value */

RdPortA()
{
#asm
	movfw	_portA
#endasm
}

WrPortB( value )
char value;
{
#asm
	movfw	_stackptr
;--	call _indr_
        movwf   _fr4
        movfw   _fr0
;
	movwf	_portB
#endasm
}

/**********************************************/
/*  The following function executes a delay based on
/*  the formula : 772*time + 12 usec
/**********************************************/
delay_ms(time)
	char time;
{
#asm
	movfw	_stackptr
	call _indr_
	movwf	_primary
_dly1ms0_
	clrf	_temp
_dly1ms_
	decfsz	_temp, f
	goto	_dly1ms_
	decfsz	_primary, f
	goto	_dly1ms_
#endasm
}

delay_sec(sec)
	char sec;
{
	int i;
	for (i = 0; i < sec; i++)
	{
		delay_ms(250);
		delay_ms(250);
		delay_ms(250);
		delay_ms(250);
	}
}