/*
	MGSCAN3.C
	
	BL14xx/MicroG or BL15xx/MicroG2

	VIOScan() is an IO scanner that reads PIO bits PB4, PB5, PB6 and PB7
	into variables PBIN4, PBIN5, PBIN6 and PBIN7, respectively. The state
	of the variables PAOUT0 to PAOUT7 are sent out of PIODA.
	
	Inputs have to be persistent for two consecutive calls of VIOScan() to be
	accepted as a change in state.
	
	The following wiring is used:

			PA5   to    TP1 or LED1
			PA6   to    TP8 or LED2
			PA7   to    TP4 or Buzzer BZ1

			PB4   to    TP2 or JP1
			PB5   to    TP7 or JP2
			PB6   to    TP3 or SW1
			PB7   to    TP6 or SW2.

	This example illustrates a different way of scanning the IO of the
	MicroG Prototyping board than mgscan1.c or mgscan2.c.
*/
	
char PBIN4, PBIN5, PBIN6 ,PBIN7;
char PAOUT0, PAOUT1, PAOUT2, PAOUT3, PAOUT4, PAOUT5, PAOUT6, PAOUT7;
char PIODBPrev;
void VIOInit();
void VIOScan();

main()
{
	VIOInit();                       // Initialize variable for VIOScan. 

	while(1)
	{
		hitwd();
		runwatch();
		VIOScan();

		PAOUT5 = PBIN4 && PBIN6;      // led1 is on if sw1 is pressed or jp1 is jumpered
		PAOUT6 = PBIN5 && PBIN6;      // led2 is on if sw1 is pressed or jp2 is jumpered
		PAOUT7 = PBIN7;               // buzzer is on if sw2 is pressed
	}
}

// VIOInit()
// Initialize variable for the VIOScan().
// Set up PIOA and PIOB ports according to this application.
void VIOInit()
{
	resPIOCA(0xff);      // all bits are set as output for PIOA
	setPIODA(0xff);      // send high's to all output
	setPIOCB(0xf0);      // 4 upper bits of PIOB are inputs
	PAOUT0 = PAOUT1 = PAOUT2 = PAOUT3 = PAOUT4 = PAOUT5 = PAOUT6 = PAOUT7 = 1;
	PBIN4 = PBIN5 = PBIN6 = PBIN7 = 0;
	PIODBPrev = 0x00;
}

// VIOScan()
// Virtual IO Scanner. Read 4 inputs and send out 8 output. Input state are read into
// PBIN4 to PBIN7 from PIOB. Output states PAOUT0 to PAOUT7 are send out of the PIODA.
// Input state has to persist for two call of VioScan to register a valid change. 
#asm
VIOScan::

pio_input:
		ld    a, (PIODBPrev)
		ld    d, a
		in0   a, (PIODB)
		and   0xf0
		ld    (PIODBPrev), a       ; store current to previous
		ld    e, a                 ; e has the current value
		xor   d                    ; a has the xor of current and previous

		ld    hl, PBIN4
		ld    b, 4

inloop:
		bit   4, a
		jr    nz, cont_inloop       ; not two consecutive value
		bit   4, e
		jr    nz, input_high    
input_low:
		ld    (hl), 0
		jp    cont_inloop
input_high:
		ld    (hl), 1
cont_inloop:
		rra
		rr    e
		dec   hl                   ; memory is allocated from the top
		djnz  inloop

pio_output:

		ld    hl, PAOUT0
		ld    c, 0x00
		ld    e, 00000001b
		ld    d, 11111110b
		ld    b, 8

outloop:

		xor   a
		cp    (hl)                 ; is it zero?
		jr    nz, or_data

and_data:
		ld    a, c
		and   d
		ld    c, a
		jr    cont_outloop
or_data:
		ld    a, c
		or    e
		ld    c, a

cont_outloop:
		rlc   e
		rlc   d
		dec   hl
		djnz  outloop

		out0  (PIODA), c        ; send out the data

		ret

#endasm