Reading Controllers

From veswiki
Jump to: navigation, search

Wait for controller movement

The simplest use of hand controller is to just pause and wait for a movement, this subroutine does just that, you call it with:

pi wait.4.controller.input

; your program, waiting for any user input

; wait for controller movement

pi	wait.4.controller.input


; when either hand control has been moved in some direction
; program continues....




; here's the actual subroutine, copy and paste to your program where convenient

wait.4.controller.input:
	; see if one of the hand controllers has moved
	clr						; clear accumulator 
	outs	0					; enable input from both hand controllers
	outs	1					; clear latch of port of right hand controller
	ins	1					; fetch inverted data from right hand controller
	com						; re-invert controller data (a %1 now means active)
	bnz	wait.4.controller.input.end		; if no movement then input is 0 -> no branch
	; check the other controller
	clr						; clear accumulator 
	outs	4					; clear latch of port of left hand controller
	ins	4					; fetch inverted data from left hand controller
	com						; re-invert controller data (a %1 now means active)
	bnz	wait.4.controller.input.end		; if anything was %1 jump to end of subroutine
	br	wait.4.controller.input			; otherwise re-test until we have some movement

wait.4.controller.input.end:
	pop						; return from subroutine

Controller directions in the register

After the hand controller data has been read you can invert it back since it is inverted when output from the controller buffer - we do that to get the real data back and because it might be easier to work with later on. The 8 bits is stored in Accumulator (A) and the bits mean this:

        direction
bit  0  right
bit  1  left
bit  2  backward
bit  3  forward
bit  4  counterclockwise
bit  5  clockwise
bit  6  pull up
bit  7  push down

So if we get the value %10000000 that means the hand controller read is being pushed down.

Port-data
%00000001  right
%00000010  left
%00000100  backward
%00001000  forward
%00010000  counterclockwise
%00100000  clockwise
%01000000  pull up
%10000000  push down

Combinations are possible to:

%10000010  push down + left

There are combinations that are impossible with a normal fully functional controller since they are opposite directions:

%11000000  push down + pull up

The "Jet Stick" however could do this as the fire button is parallel to the push down function.

After reading the controller/s you can store the result in a register (or in available RAM) for use later or check directly which direction was chosen. Let's suppose you have a game where you can move forward, backward, right or left with the right hand controller. If we store the result of the controller in register 8, this is how to do it:

Store result for later use

store.right.controller.input:
	
	clr
	outs	0
	outs	1						; check right hand controller
	ins	1
	com							; re-invert controller data
	lr	8, A						; store result in register 8

store.right.controller.input.end:


Later in the program we can load the movement and mask away the directions we're interested in.


	; 	program program
	; 	...
	
	lr	A, 8						; copy register 8 to Ackumulator
	ni	%00001111					; AND result and only keep the last nibble
	lr	8, A						; back up result in r8 again

	;	...
	;	program continues


We now have one of these bit patterns in r8:

%00000000	no movement
%00000001	right
%00000010	left
%00000100	backward
%00000101	backward + right
%00000110	backward + left
%00001000	forward
%00001001	forward + right
%00001010	forward + left

Nothing else is possible with your normal controller unless something is broken.

The controller value can then be compared to the values above to decide what to do next, move the player perhaps.

Reading the four console buttons

This code reads the buttons, you can then mask this result similar to the hand controller:

	; read buttons
	ins	0				; get input from port 0
	com					; invert 
	lr	4, A				; store button result in register 4
	li	128				; load timer value for debounce
	lr	5, A				; in register 5
debounce: 			; this is a delay to wait until button contacts stops bouncing
	ds	5				
	bnz	debounce			; decrease r5 until zero
	lr	A, 4				; load button result into Ackumulator again
	ni	%00000010			; mask out button #2
	bnz	main.buttons.used.two		; not zero means button 2 was pressed
	lr	A, 4				; load read result into A again
	ni	%00000001			; check if it was button #1
	bnz	main.buttons.used.one		; if that's not 0 it means button 1 was held

	br	main.continue			; continue program

The intelligent reader has already figured out the rest of the inputs available:


%00000001  button 1
%00000010  button 2
%00000011
%00000100  button 3
%00000101
%00000110
%00000111
%00001000  button 4
%00001001
%00001010
%00001011
%00001100  button 4 + 3
%00001101
%00001110
%00001111   all buttons pressed

Combinations are pretty clear.

Conclusion

Read right hand controller this way:

	clr
	outs	0
	outs	1
	ins	1
	com		

Read left hand controller this way:

	clr
	outs	4
	ins	4
	com

Read buttons with:

	ins	0
	com

	; you may need to debounce as described above

And you have the result in A