
;Servo test routine, serv675C
;Author EdwardM

	__CONFIG _CP_OFF & _CPD_OFF & _WDT_OFF & _MCLRE_OFF & _BODEN_OFF & _HS_OSC
	#define 	__12F675
	#include 	<12f675.inc>
;====================================
;   Pin Defs
;====================================

; Pin1......Vdd
; Pin2......GP5
; Pin3......CLKOUT............TEST.......OUT
; Pin4......GP3/MCLR/Vpp......CENTRE.....IN
; Pin5......AN2...............POT........Analog
; Pin6......GP1/ICPCLK........SWEEP......IN
; Pin7......GP0/ICPDTA........PWM........OUT
; Pin8......VSS
	                                                                              
;====================================
;   RAM 0x20 to 0x5F
;====================================
CounterA		equ		0x20
CounterB		equ		0x21
CounterC		equ		0x22
CounterD		equ		0x23
Timer_rtn		equ		0x24
temp_loops		equ		0x25
us_loops		equ		0x26
tempf			equ		0x27
set_centre		equ		0x28
old_ADC			equ		0x29
ADC_low			equ		0x2A
ADC_high		equ		0x2B
mode_state		equ		0x2C
LOW_count		equ		0x2D
HIGH_count		equ		0x2E
last_low		equ		0x2F
last_high		equ		0x30
max_low			equ		0x31
max_high		equ		0x32
min_low			equ		0x33
min_high		equ		0x34
inc_high		equ		0x35
inc_low			equ		0x36
inc_up			equ		0x37
init_inc		equ		0x38
last_pos_high	equ		0x39
last_pos_low	equ		0x3A


		Org		0x00
		goto	main

table	addwf	PCL,f
	retlw	D'254'
	retlw	D'205'
	retlw	D'153'
	retlw	D'102'
	retlw	D'77'
	retlw	D'62'
	retlw	D'48'
	retlw	D'34'
	retlw	D'26'
	retlw	D'19'
	retlw	D'13'
	retlw	D'9'
	retlw	D'6'
	retlw	D'4'
	retlw	D'2'
	retlw	D'1'




;================================
;  16 bit Comparison MAX
;================================
compMAX	
	movf	max_high,w
	subwf	ADC_high,w
	btfss	STATUS,Z
	goto	res16A
	movf	max_low,w
	subwf	ADC_low,w
res16A
	return
;================================
;  16 bit Comparison MIN
;================================
compMIN	
	movf	ADC_high,w
	subwf	min_high,w
	btfss	STATUS,Z
	goto	res16B
	movf	ADC_low,w
	subwf	min_low,w
res16B
	return


main
	call	initial_setup
main_loop
	call	set_20ms_frame
	call	set_position	;Position set from previous loop
	call	check_pbuttons	;Check pushbuttons for mode change
	call	check_mode		;Get current test mode
	call	wait_end20ms
	goto	main_loop
	
;================================
; Wait for end of 20ms frame
;================================
wait_end20ms
	btfss	PIR1,0
	goto	wait_end20ms
	return
;================================
; Which mode are we in?
;================================
check_mode
	clrf	inc_high
	clrf	inc_low
	iorlw	0x00			;w=0xFF if change
	btfsc	STATUS,Z		;
	goto	nochange		;If no jump, status has changed
	btfsc	mode_state,0	;Centre?
	goto	do_centre
	btfsc	mode_state,1
	goto	do_sweep		;must be sweep
	goto	changetopot
do_centre
	call	get_ADC
	call	set_ADC_limits
dc1
	movlw	0xFF			;1.5ms
	movwf	LOW_count
	movlw	0x01
	movwf	HIGH_count
	clrf	mode_state
	bsf	mode_state,0
	return
nochange
	clrf	inc_low
	clrf	inc_high
	
	btfsc	mode_state,0	;Centre
	goto	check_centre
	btfsc	mode_state,1	;Sweep
	goto	check_sweep		;else set by pot position
changetopot
	call	get_ADC
	movf	ADC_high,w
	movwf	HIGH_count
	movf	ADC_low,w
	movwf	LOW_count
	clrf	mode_state
	bsf	mode_state,2
	return
check_centre
	call	get_ADC
	call	compMAX
	btfsc	STATUS,C		;Carry set then out of range, set posn to pot
	goto	changetopot
	call	compMIN
	btfsc	STATUS,C
	goto	changetopot
	goto	dc1
	return
check_sweep
	call	get_ADC
	call	div64
	call	SetCountper20ms
	btfss	inc_up,0
	goto	cs1
	call	add_inc
	return
cs1
	call	sub_inc
	return
do_sweep
	call	get_ADC
	call	div64
	call	SetCountper20ms
	bsf	inc_up,0
	call	add_inc
	return
add_inc
	movfw	inc_low
	addwf	last_pos_low,f
	btfsc	STATUS,C
	incf	last_pos_high,f
	btfss	last_pos_high,2
	goto	ai1
	movlw	0x03
	movwf	HIGH_count
	movlw	0xFF
	movwf	LOW_count
	bcf	inc_up,0
	return
ai1
	movfw	last_pos_high
	movwf	HIGH_count
	movfw	last_pos_low
	movwf	LOW_count
	return		
sub_inc
	movfw	inc_low	;last_pos_low
	subwf	last_pos_low,w	;inc_low,w
	movwf	LOW_count
	movfw	last_pos_high
	btfss	STATUS,C
	addlw	0xFF
	movwf	HIGH_count
	btfss	HIGH_count,7
	return
	movlw	0x00
	movwf	HIGH_count
	movwf	LOW_count
	bsf	inc_up,0
	return
div64
	rrf	ADC_low,f	
	rrf	ADC_low,f
	rrf	ADC_low,f
	rrf	ADC_low,f
	rrf	ADC_low,f
	rrf	ADC_low,f
	movlw	0x03
	andwf	ADC_low,f
	rlf	ADC_high,f
	rlf	ADC_high,f
	movlw	0x0C
	andwf	ADC_high,w
	iorwf	ADC_low,w
	return
	
SetCountper20ms

	call	table
	movwf	inc_low
	clrf	inc_high
	return
;================================
;  Check ADC
;================================
get_ADC
	movlw	0x8B		;Start ADC
	movwf	ADCON0
sp2
	btfsc	ADCON0,1	;check go/done bit for end of conversion
	goto	sp2
	bsf	STATUS,RP0		;set bank 1
	movf	ADRESL,w
	bcf	STATUS,RP0		;set bank 0
	movwf	ADC_low		;LOW_count
	movwf	LOW_count
	movf	ADRESH,w
	movwf	ADC_high	;HIGH_count
	movwf	HIGH_count
	return
;========================================
;  Set ADC limits
;========================================
set_ADC_limits
	clrw
	movwf	max_low
	movwf	max_high
	movwf	min_low
	movwf	min_high

	movf	ADC_low,w
	addlw	D'10'
	movwf	max_low
	movf	ADC_high,w
	btfsc	STATUS,C
	addlw	0x01
	movwf	max_high

	movlw	D'10'
	subwf	ADC_low,w
	movwf	min_low
	movf	ADC_high,w
	btfss	STATUS,C
	addlw	0xFF
	movwf	min_high
	movlw	0x00
	subwf	min_high,f
	return
;========================================
; Check pushbutton state for mode change
;========================================
check_pbuttons
	btfss	GPIO,GPIO3		;Centre?
	goto	mode_centre
	btfss	GPIO,GPIO1		;Sweep?
	goto	mode_sweep
	retlw	0x00			;No change
mode_centre
	clrf	mode_state
	bsf	mode_state,0
	retlw	0xFF
	clrf	inc_low
	clrf	inc_high
mode_sweep
	clrf	mode_state
	bsf	mode_state,1
	retlw	0xFF	
;================================
;  Set PWM output on
;================================
set_20ms_frame
	bsf	GPIO,0				;Output on
	movlw	0x3B			;Set timer to 20ms-setup time @10MHz
	movwf	TMR1H
	movlw	0xBB
	movwf	TMR1L
	movlw	0x01			
	movwf	T1CON			;Timer enable
	bcf	PIR1,0				;Clear timer overflow flag
	return

;================================
;  Set position
;================================
set_position
	call	init_delay		;Nominal 1ms delay
	movfw	HIGH_count
	movwf	last_pos_high
	movfw	LOW_count
	movwf	last_pos_low
	clrw
	iorwf	LOW_count,f
	btfsc	STATUS,Z
	goto	low_zero
low_nonzero
	decfsz	LOW_count,f
	goto	low_nonzero
low_zero
	clrw
	iorwf	HIGH_count,f
	btfsc	STATUS,Z
	goto	high_zero
do_loops
	decfsz	LOW_count,f
	goto	do_loops
	decf	HIGH_count,f
	goto	low_zero
high_zero
	bcf	GPIO,0				;Output off
	return

init_delay
	movlw	D'3'
	movwf	CounterB
	movlw	D'210'
	movwf	CounterA
loop	decfsz	CounterA,1
	goto	loop
	decfsz	CounterB,1
	goto	loop
	return
us_delay

	movlw	D'4'
	movwf	CounterA
loopus	decfsz	CounterA,1
	goto	loopus
	nop
	nop
	nop
	nop
	nop
	return
;================================
;  Initial setup
;================================                                                                                 
initial_setup
	bcf	STATUS,RP0			;set bank 0
	clrf	GPIO			;set GPIO 's to 0
	movlw	07H				;
	movwf	CMCON			;Comparator control - off
	bsf	STATUS,RP0			;set bank 1
	movlw	0x24
	movwf	ANSEL
	movlw	0x3E			;GP2/AN2 input only
	movwf	TRISIO			;all others output, bank 1

	bcf	STATUS,RP0			;set bank 0
	movlw	0x89			;Initialise adc
	movwf	ADCON0			;bank 0
	bcf	mode_state,0		;Centre
	bcf	mode_state,1		;Sweep
	bsf	mode_state,2		;Pot
	call	get_ADC
	clrf	inc_low
	clrf	inc_high
	movlw	0x01
	movwf	init_inc
	return
	end
