;Stepper motor controller

 LIST P=12F683, R=DEC
 INCLUDE "p12f683.inc"

 __CONFIG _FCMEN_OFF & _IESO_OFF & _CP_OFF & _CPD_OFF & _BOD_OFF & _PWRTE_ON & _MCLRE_OFF & _WDT_OFF & _INTRC_OSC_NOCLKOUT

 CBLOCK 0x20 	
step						; step sequence number
shifter
ti, del						; variables used for delay
 ENDC

 ORG 0                   	; start program at the beginning of mem
main    
	movlw	7
	movwf	CMCON0			; disable comparator

	clrf 	GPIO 			; initialize port
	bsf		STATUS, RP0		; switch to BANK 1 
	movlw	b'011000'		; configure pins GPIO4 and 3 for input
	movwf	TRISIO ^ 0x80	; and others for output
	
	movlw	b'00011000'		; enable analog input AN3
	movwf	ANSEL ^ 0x80	; and set ADC freq = FOSC/8

	bcf		STATUS, RP0		; back to BANK 0
	movlw	b'1101'			; ADC on and enable input at AN3
	movwf	ADCON0 

	clrf	step			; initialize used variables
	clrf	shifter			; shifter variable for debouncing
	decf	shifter, f

	bcf		PIR1, ADIF		; clear ADC interrupt flag
	clrf	ti				; clear delay
	clrf	del
	movlw	10
	movwf	del

loop:						; Forward rotation sequence
	movlw	b'011000'
	andwf	GPIO, f			; clear motor control bits
	call	getStep			; get the next rotation code in WREG
	addwf	GPIO, f			; load this code to output
	call	delay

	btfss	PIR1, ADIF		; ADC value ready?
	 goto	proceed			; NO - proceed
	bcf		PIR1, ADIF		; YES - clear ADC interrupt flag
	movf	ADRESH, w		; setup new delay value
	movwf	del
	bcf		STATUS, C		; divide del by 4 for a smoother control
	rrf		del, f
	bcf		STATUS, C
	rrf		del, f

proceed
	
    bcf		STATUS, C		; clear C flag
	rlf		shifter, f		
    btfss	GPIO, 3			; skip if clear 
	 bsf	shifter, 0

	movf	shifter, f
	btfss	STATUS, Z
	 incf	step, f
	
    movf	shifter, f
    btfsc	STATUS, Z
	decf 	step, f			; update step number (0 - 7)

	movlw	7
	andwf	step, f
    bsf		ADCON0, GO		; and start AD conversion
	goto	loop

getStep						; stepper codes table
	movf	step, w
	addwf	PCL, f		
	retlw	b'100110'
	retlw	b'100010'
	retlw	b'100000'
	retlw	b'100001'
	retlw	b'000001'
	retlw	b'000101'
	retlw	b'000111'
	retlw	b'000110'

delay
	movf	del, w
	movwf	ti				; set ti = del

	movlw	50
	addlw	-1				; this loop takes 250
    nop						; CPU op cycles
	btfss	STATUS, Z
	 goto	$-3

	movf	ti, w			; update loop variable
	btfsc	STATUS, Z
	 return
	decf	ti, f			
    goto	delay+2

 END
