; kaleidoscope.asm					2007/03/21 14:13:59

; GP5 B+	output H	; StepMotor B+ coil
; GP4 A+	output H	; StepMotor A+ coil
; GP3 MCLRE	MCLRE		; MCLRE
; GP2 B-	output H	; StepMotor B- coil
; GP1 A-	output H	; StepMotor A- coil
; GP0 AN0	analog		; 回転数 or 回転方向
; TRISIO	b'xx001001'
;
;  AD変換値	動作
;   0	 15	変速、正逆転
;  16	 31	CW min
;  32	 47
;  48	 63
;  64	 79
;  80	 95
;  96	111	CW max
; 112	127	停止
; 128	143	停止
; 144	159	CCW max
; 160	175
; 176	191
; 192	207
; 208	223
; 224	239	CCW min
; 240	255	変速、正逆転

	list		p=PIC12F675
	#include	<P12F675.INC>

	__CONFIG	 _CP_OFF & _CPD_OFF & _BODEN_OFF & _MCLRE_ON & _WDT_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT

	CBLOCK	20H
	buff			; 汎用
	ANO_buff		; AN0入力値
	Pat_No			; 出力パターンNo
	Direct			; 回転方向 -1/1=ccw/cw
	PulW_Ref		; パルス幅設定値
	PulW_Cnt		; パルス幅カウンタ
	Cnt_VR			; 変速パルス幅設定値 0～95 255-(Cnt_VR+16) ⇒ PulW_Ref
	Vdirect			; 変速方向 -1/1=加速/減速
	Cnt_LSB			; 変速タイマー下位(4.096msec/count)
	Cnt_MSB			; 変速タイマー上位(約1.05sec/count)
	cnt20u			; カウンタ for 20μsec timer

	W_temp
	FSR_temp
	STATUS_temp
	PCLATH_temp
	ENDC

#define sel_bank0	bcf	STATUS,RP0
#define sel_bank1	bsf	STATUS,RP0

	org	0
init	sel_bank1
	bcf	PCON,1		; パワーONでリセットする
	bsf	PCON,0		; ブラウンアウトリセットしない
	goto	start

	org	4
	movwf	W_temp		; save W
	movf	STATUS,W
	movwf	STATUS_temp	; save STATUS
	movf	FSR,W
	movwf	FSR_temp	; save FSR
	movf	PCLATH,W
	movwf	PCLATH_temp	; save PCLATH
	call	intrqt
	movf	PCLATH_temp,W
	movwf	PCLATH		; restore PCLATH
	movf	FSR_temp,W
	movwf	FSR		; restore FSR
	movf	STATUS_temp,W
	movwf	STATUS		; restore STATUS
	swapf	W_temp,F
	swapf	W_temp,W	; restore W
	retfie

start	call	h'3FF'		; 4MHz発振の補正値を入れる
	movwf	OSCCAL
	movlw	b'00010001'	; fosc/8  AN0
	movwf	ANSEL
	sel_bank0
	clrf	GPIO		; GPIOを初期化する
	movlw	b'00000111'	; コンパレータ未使用
	movwf	CMCON
	movlw	b'00000000'	; select AN0
	movwf	ADCON0		; 左詰め Vdd turn off A/D
	sel_bank1
	movlw	b'00001001'	; GP5,GP4,GP2,GP1 output GP3 input GP0 analog 
	movwf	TRISIO
	movlw	b'11010111'	; pullup off TMR0CLK=osc/4
	movwf	OPTION_REG	; prescaler=1/256  256μsec
	clrf	IOC		; disable interrupt on change GPIO 
	sel_bank0
	clrf	INTCON
	movlw	ANO_buff
	movwf	FSR
start1	clrf	INDF		; clear memory
	incf	FSR,F
	movlw	PCLATH_temp+1
	subwf	FSR,W
	btfss	STATUS,Z
	goto	start1
	call	ctl_ini
	movlw	d'1'		; cw設定(1)
	movwf	Direct
	movlw	d'240'		; set timer value 256-4.096ms/0.256ms = 240
	movwf	TMR0		; TMR0 = 4.096ms
	movlw	b'10100000'	; GIE=1,T0IE=1
	movwf	INTCON		; interrupt interrupt enable
	nop

M_Loop	nop
	nop
	goto	M_Loop

; -------------------------------interrupt routine-------------------------

intrqt	btfss	INTCON,T0IF	; skip if time out interruption
	return			; return at illegal interrupt
	movlw	d'240'		; set timer value 256-4.096ms/0.256ms = 240
	movwf	TMR0		; TMR0 = 4.096ms
	bcf	INTCON,T0IF	; clear timer int flag
	call	ad_conv

	movlw	$/0x100
	movwf	PCLATH
	swapf	ANO_buff,W
	andlw	h'0F'
	addwf	PCL,F

	goto	v_rot		; 0 変速、正逆転
	goto	r_cw		; 1 CW max
	goto	r_cw		; 2
	goto	r_cw		; 3
	goto	r_cw		; 4
	goto	r_cw		; 5
	goto	r_cw		; 6 CW min
	goto	ctl_ini		; 7 停止
	goto	ctl_ini		; 8 停止
	goto	r_ccw		; 9 CCW min
	goto	r_ccw		; A
	goto	r_ccw		; B
	goto	r_ccw		; C
	goto	r_ccw		; D
	goto	r_ccw		; E CCW max
	goto	v_rot		; 変速、正逆転

;	制御初期化(停止)

ctl_ini	clrf	GPIO		; モータ停止
	clrf	PulW_Ref	; パルス幅設定値
	movlw	d'1'
	movwf	PulW_Cnt	; パルス幅カウンタ初期値設定
v_init	clrf	Cnt_VR		; 変速パルス幅設定 0 ((Cnt_VR+2)*2 ⇒ PulW_Ref)
	clrf	Cnt_MSB		; 変速タイマー上位(約1.05sec/count)
	movlw	d'1'
	movwf	Vdirect		; 変速方向 減速設定(1)
	movwf	Cnt_LSB		; 変速タイマー下位(4.096msec/count)
	return

;	変速、正逆転動作

v_rot	decf	Cnt_LSB,F	; 変速タイマー下位-1
	comf	Cnt_LSB,W
	btfsc	STATUS,Z	; skip if 変速タイマー下位>=0
	decf	Cnt_MSB,F	; 変速タイマー上位-1
	movf	Cnt_LSB,W
	iorwf	Cnt_MSB,W
	btfss	STATUS,Z	; skip if 変速タイマー=0
	goto	pat_out
	movlw	h'7A'		; 変速タイマー 500msec設定
	movwf	Cnt_LSB
	clrf	Cnt_MSB
	movf	Cnt_VR,W	; 変速パルス幅 増減
	addwf	Vdirect,W
	andlw	h'F'
	movwf	Cnt_VR
	btfss	STATUS,Z	; skip if 変速パルス幅=0
	goto	v_rot1
	movlw	d'1'		; 変速方向 減速設定(1)
	goto	v_rot2

v_rot1	sublw	d'95'
	btfss	STATUS,Z	; skip if 変速パルス幅=95
	goto	v_rot3
	comf	Direct,F	; 回転方向変更
	incf	Direct,F

	movlw	h'FF'		; 変速方向 加速設定(-1)
v_rot2	movwf	Vdirect
v_rot3	movf	Cnt_VR,W
	addlw	d'16'		; W=Cnt_VR+16
	movwf	PulW_Ref
	comf	PulW_Ref,F
	goto	pat_out

;	定速動作

r_ccw	call	v_init
	movlw	h'FF'		; ccw設定(-1)
	movwf	Direct
	movf	ANO_buff,W
	goto	r_cw1

r_cw	call	v_init
	movlw	d'1'		; cw設定(1)
	movwf	Direct
	comf	ANO_buff,W
r_cw1	movwf	PulW_Ref	; パルス幅設定

;	モータ駆動

pat_out	decfsz	PulW_Cnt,F	; skip if パルス幅カウンタ=0
	return
	movf	PulW_Ref,W
	movwf	PulW_Cnt
	movf	Pat_No,W	; Pat_No=出力パターンNo
	addwf	Direct,W	; 回転方向
	andlw	d'7'
	movwf	Pat_No		; 出力パターンNo変更
	call	Drv_sig
	movwf	GPIO
	return

;	GP5 B+	GP4 A+	GP2 B-	GP1 A-

Drv_sig	movlw	$/0x100		; 出力データ設定
	movwf	PCLATH
	movf	Pat_No,W
	addwf	PCL,F

	DT	b'00010000'	; A+    ON 1相励磁
	DT	b'00100000'	;    B+ ON
	DT	b'00000010'	; A-    ON
	DT	b'00000100'	;    B- ON
	DT	b'00010000'	; A+    ON
	DT	b'00100000'	;    B+ ON
	DT	b'00000010'	; A-    ON
	DT	b'00000100'	;    B- ON

;	A/D変換

ad_conv	movlw	b'00000001'	; select AN0
	movwf	ADCON0
	call	wait2u		; 18+2μsec wait
	bsf	ADCON0,GO	; A/D start
adloop	btfsc	ADCON0,GO	; skip if A/D done
	goto	adloop
	movf	ADRESH,W	; get A/D data
	movwf	ANO_buff	; A/D -> ANO_buff
	movlw	b'00000000'	; turn off A/D
	movwf	ADCON0
	return

;	20μsec wait

wait2u	movlw	d'5'		; 1 (3n+3)*1サイクル時間(4/fosc)
	movwf	cnt20u		; 1	4MHz 4/4=1μsec 18μsec
wait21	decfsz	cnt20u,F	; 1*(n-1)+2
	goto	wait21		; 2*(n-1)
	return			; 2

	end
