; ;******************************************************************* ; ; 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 __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 ;