;
;*******************************************************************
;
;	Experimental quadrature decoder for 12F510 
;	Input: 	Quadrature signals on GP0, GP1. "Reverse" control on GP3
;			Debounce control on GP2 0 to 2.5mS
;	Output: Low going pulse on on GP5, Direction indicator on GP4
;
;	Connect low going quadrature pair to pins 6 and 7, 2K pot wiper 
;	on pin 5, ends to VDD and VSS.
;	Program generates 10uS low going pulse output on pin 2, 
;	direction output on pin3
;	connect pin4 to 0V and reboot to reverse direction
;
;	V1.1	CMS 03/03/2008
;
;*******************************************************************
;
#include <p12F510.inc>
	__config (_IOSCFS_OFF & _MCLRE_OFF & _CP_OFF & _WDT_OFF & _IntRC_OSC)
;
#define	CLKBIT	GPIO,5
#define	DIRBIT	GPIO,4
#define	REVBIT	GPIO,3
#define	GO_ADC	ADCON0,1
;
MSKBYT	equ	3				; quadrature input bit mask
;
;	reserve some space for variables
;
    cblock 0x0a	; 
;
temp1
temp2
target
count
;
    endc
;
;	reserve 16 bytes for a state table. do not move or edit
;
    cblock 0x10
;
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'00001111'			; bit0, bit1 bit2 and bit3 are inputs
    tris	GPIO				;
;
	clrf	GPIO				; all outputs off
	bsf		CLKBIT				; clock pulse active lo
;
	movlw	B'11110111'			; no comparators
	movwf	CM1CON0				;
;
	movlw	B'01111001'			; ADC on, intck/4 ch2 
	movwf	ADCON0				;
	bsf		GO_ADC				; start conversion
;
;	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	load				; start address of load 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				; 	
;
;	main loop
;
roll equ	$
;
	movf	ADRES,w				; get convertion result
	movwf	target				; and save as debounce target
	movf	target,f			; seem to need this to set zero flag
	btfsc	STATUS,Z			; avoid zero
	incf	target,f			;
;
load equ	$
;
	movfw	target				; reload debounce target
	movwf	count				;
;
	bsf		CLKBIT				; clock signal to inactive (hi)
;
;	get data
;
grab equ	$
;
	movf	GPIO,w				; grab data
	andlw	MSKBYT				; mask
	subwf	temp1,f				; compare with previous
	movwf	temp1				; save new
;
	btfss	STATUS,Z			; reload target if different (bounce)
	goto	load				;
;
	movf	count,f				; test counter zero flag
	btfss	STATUS,Z			; pass new code once only 
	decfsz	count,f				; unchanged data so
	goto	grab				; decrement debounce counter
;
;	we have a consistent code
;
	bsf		GO_ADC				; ADC must be ready, result is in 13 cycles 
;
	bcf		STATUS,C			; not strictly necessary but safer 	1)
	rlf		temp2,f				; rotate previous data right twice	2)
	rlf		temp2,w				; into w							3)
;
	iorwf	temp1,w				; form four-bit transition code		4)
;
	iorlw	0x10				; form table offset address 		5)
	movwf	FSR					; to jump vector					6)
;
	movf	temp1,w				; update "previous" value			7)
	movwf	temp2				;									8)
;
	movf	INDF,w				; get vector						9)
;
	movwf	PCL 				; and go							10)
;
;	note the previous instuction was a computed "goto"	
;
cw	equ		$
;
	bcf		DIRBIT				; clockwise increment				11)
	bcf		CLKBIT				; clock to active (lo)				12)
	goto	roll				;									13, 14)
;
ccw	equ		$
;
	bsf		DIRBIT				; anti-clockwise increment			11)
	bcf		CLKBIT				; clock to active (lo)				12)
	goto	roll				;									13, 14)
;
	end
;
