; TOGGLE port (in w), pin
; Toggles (inverts) the state of the specified port and pin.


; Device data and reset vector

	device	pic16c55,xt_osc,wdt_off,protect_off
	reset	start

	org	8
pin	ds	1	; Pin number to set (0-7).

; Variables for the demo program--not required by Toggle.
p_index	ds	1	; Copy of pin number, port number.
temp	ds	1	; Temporary variables for time delay
temp2	ds	1	; between outputs.

	org	0

; Table to convert pin number (0-7) into bit mask (00000001b to 10000000b).
Pinz	jmp	pc+w
	retw	1,2,4,8,16,32,64,128

; The following demonstration code should show the value of being able to
; toggle a particular bit of a port based on a calculation performed while the
; program is running. As the variable p_index is incremented from 0 to 15,
; it is used to specify the pin and port to invert using Toggle.

start	mov	!rb, #0 ; All outputs on rb.
	mov	!rc, #0 ; All outputs on rc.
	mov	rb,#10101010b	; Put a pattern of alternating lights
	mov	rc,#10101010b	; onto rb and rc.
	clr	p_index ; Clear p_index.
:loop	mov	pin,#7	; Copy three lsbs of p_index into
	AND	pin,p_index	; variable pin.
	mov	w,#1	; IF p_index.3 = 0

	snb	p_index.3	; THEN w = 1
	mov	w,#2	; ELSE w = 2
	call	Toggle
	call	delay	; Wait a while between toggles.
	inc	p_index ; Next pin/port.
	sb	p_index.4	; IF p_index < 15 (rc.7)
	jmp	:loop	; THEN :loop ELSE done
done	jmp	$	; Endless loop.

; To use the routine Toggle, put the pin number into the variable pin
; and the port number into w. Then call Toggle.

Toggle	mov	fsr,w	; Point to the port number.
	ADD	fsr,#RA ; Add offset for port RA.
	mov	w,pin
	call	Pinz	; Get bit mask from the table.
	XOR	indirect,w	; Invert the selected bit
	ret

; Delay routine for demonstration. Not required by Toggle.

delay	djnz	temp,delay	; Time delay to provide spacing
	djnz	temp2,delay	; between highs.
	ret

	end