;
;*******************************************************************
;
;	Experimental quadrature decoder for 12F508/12F509 
;	Input: Quadrature signals on GP0, GP1. "Reverse" control on GP3
;	Output: Low going pulse on on GP5, Direction indicator on GP4
;
;	Connect low going quadrature pair to pins 6 and 7
;	15uS low going pulse output on pin 2, direction output on pin3
;	connect pin4 to 0V and reboot to reverse direction
;
;	V1.0	CMS 29/02/2008
;
;*******************************************************************
;
#include <p12F509.inc>
	__config (_MCLRE_OFF & _CP_OFF & _WDT_OFF & _IntRC_OSC)
;
#define	CLKBIT	GPIO,5
#define	DIRBIT	GPIO,4
#define	REVBIT	GPIO,3
MSKBYT	equ	3				; quadrature input bit mask
;
;	reserve some space for variables
;
    cblock 0x08
;
temp1
temp2
;
    endc
;
    cblock 0x10
;
;	reserve 16 bytes for a state table. do not move or edit
;
none1		;0	;0000
cw1			;1	;0001
ccw1		;2	;0010
inv1		;3	;0011
ccw2		;4	;0100
none2		;5	;0101
inv2		;6	;0110
cw2			;7	;0111
cw3			;8	;1000
inv3		;9	;1001
none3		;a	;1010
ccw3		;b	;1011
inv4		;c	;1100
ccw4		;d	;1101
cw4			;e	;1110
none4		;f	;1111
;
    endc
;
	org 0     					; osccal value in w on power up
	movwf	OSCCAL				;
;
	movlw	B'10000111'			; no wake on pin change, weak pull-ups on
	option						; internal timer clock, prescale 256 
;
	movlw   B'00001011'			; bit0, bit1 and bit3 are inputs
    tris	GPIO				;
;
	clrf	GPIO				; all outputs off
	bsf		CLKBIT				; clock pulse active lo
;
;	load up the jump-table and curse Harvard
;
	movlw	grab				; start address of grab routine
;
	movwf	0x10				; into all "no change"
	movwf	0x15				; locations
	movwf	0x1a				; 	
	movwf	0x1f				; 	
;
	movlw	inv					; start address of inv routine
;
	movwf	0x13				; into all "non valid"
	movwf	0x16				; locations
	movwf	0x19				; 	
	movwf	0x1c				; 	
;
	movlw	cw					; start address of cw routine
;
	btfsc	REVBIT				; normal or reverse output required?
	movlw	ccw					; start address of ccw routine
;
	movwf	0x11				; into all "clockwise" locations	
	movwf	0x17				; 	
	movwf	0x18				; 	
	movwf	0x1e				; 	
;
	movlw	ccw					; start address of ccw routine
;
	btfsc	REVBIT				; normal or reverse output required?
	movlw	cw					; start address of cw routine
;
	movwf	0x12				; into all "anticlockwise" locations
	movwf	0x14				; 	
	movwf	0x1b				; 	
	movwf	0x1d				; 	
;
	goto	grab				;
;
;	process input bits
;
grab equ	$
;
	movf	temp1,w				; save previous
	movwf	temp2				; input
;
	movf	GPIO,w				; grab data
	andlw	MSKBYT				; mask
	movwf	temp1				; save
;
	bcf		STATUS,C			; not necessary but tidier
	rlf		temp2,f				; rotate previous data right twice
	rlf		temp2,w				; 
;
	iorwf	temp1,w				; form four-bit transition code
;
	iorlw	0x10				; form table offset address 		
;
	movwf	FSR					; get jump vector
	movf	INDF,w				;
;
	bsf		CLKBIT				; clock signal to inactive (hi)
;
	movwf	PCL 				; and go
;
cw	equ		$
;
	bcf		DIRBIT				; clockwise increment
	bcf		CLKBIT				; clock to active (lo)
	goto	grab				;
;
ccw	equ		$
;
	bsf		DIRBIT				; anti-clockwise increment
	bcf		CLKBIT				; clock to active (lo)
	goto	grab				;
;
inv	equ		$
;
	bcf		CLKBIT				; this should never happen so we 
	goto	grab				; assume overspeed and no direction swap 
;
	end
