;************************************************************************************
;踏切遮断機用サーボモータ制御プログラム　（PIC12F629)
;スイッチＯＮ（GP4："L"）でサーボモータを駆動し、　ＯＦＦ（GP4："H"）で元の位置に戻る
;サーボホーンの振れ角度はMCNTの値を変更することで調整可能
;GP4（プルアップ）:（GP4："L"）にするとサーボモータ駆動　１で反対方向に駆動
;（ＯＮ（GP4が"L"）になってから2秒後に動作開始）
;GP5:電源ON時にGP5が"L"の場合遅延モードとなり、GP4が"L"になってから６秒後に動作開始　
;GP0：GP4：がL"で動作を開始したときに点灯
;GP1：動作開始後、サーボモータが回りきった時点で点灯（遮断管が降りた状態）
;GP2：サーボモータ出力
;						PIC12F629
;						+-------+
;		+5V  		--	|		| -- 	GND
;	　動作遅延モード	--	|		| --	LED出力(GP4　"L"入力時点灯)
;		スイッチ入力	--	|		|　--	LED出力(サーボ動作完了　遮断機が下りたら点灯)
;		未使用		--	|		|　--	サーボモータ出力
;						+-------+
; Ver1.00　初版  cross100.asm
;	     PIC12F629 Dataseet (DS41190F)　　　　　　　　
;copyright(c) 2012　名古屋電鉄		http://www007.upp.so-net.ne.jp/nagoden/
;************************************************************************************

	list	p=12f629
	#include	<p12f629.inc>

	__CONFIG   _CP_OFF & _CPD_OFF & _BODEN_ON & _MCLRE_OFF & _WDT_ON & _PWRTE_ON & _INTRC_OSC_NOCLKOUT 

	#define		LEDS	GPIO,0	;ＧＰ４がＬになったら点灯（起動確認用）
	#define		LEDO	GPIO,1	;サーボモータが回りきった（遮断管がおりた）時に点灯
	#define		SERVO	GPIO,2
	#define		MCNT	d'88'	;振れ幅（約90°・1ms）を255で分割した時の位置　1～255　
								;この値でホーンの振れ幅を決定します。
	CNT1		EQU	0x20	;タイマー用
	CNT2		EQU	0x21	;タイマー用
	CNT3		EQU	0x22	;ホーンの位置制御用
	CNT4		EQU	0x23	;ホーンの現在位置
	CNT5		EQU 0x24	;最大値計算用
	DIR			EQU 0x25	;ホーン位置フラグ
	delay_f		EQU	0x26	;起動遅延フラグ2（GP5を起動時に０にしておくことで起動時間を遅延させる）
	delay_s		EQU	0x27	;起動遅延フラグ1（遮断機が下りはじめる時間の遅延処理）
	delay_c		EQU	0x28	;動作遅延フラグ1（降りる処理の遅延フラグ）
	CNT6		EQU	0x29	;ディレイカウンタ用　（降りはじめの遅延時間）
	CNT7		EQU	0x2a	;ディレイカウンタ用（ワーク用）

	ORG		0x000
	goto	main
	ORG		0x004
	retfie
main
	;内部クロック補正
		bsf		STATUS,RP0 ; bank=1
		call	0x3ff
		movwf	OSCCAL
		bcf		STATUS,RP0 ; bank=0
	;割り込みを禁止
		clrf	INTCON
	;コンパレータ使用禁止
		movlw	0x07
		movwf	CMCON
	;GPIO 0,1,2を出力、3,4,5を入力
		bsf		STATUS,RP0 ;bank=1
		bcf		TRISIO,0
		bcf		TRISIO,1
		bcf		TRISIO,2
		bsf		TRISIO,3
		bsf		TRISIO,4
		bsf		TRISIO,5
		bcf		STATUS,RP0 ;bank=0
	;タイマークロックを内部、T1をオフ
		bcf		T1CON,T1OSCEN
		bcf		T1CON,TMR1CS
		bcf		T1CON,TMR1ON
	; WDT にプリスケーラを割当
		clrf	TMR0		; TMR0 をクリア
		bsf		STATUS, RP0	; バンク1に切り替え
		clrwdt				; WDT とプリスケーラのクリア
		movlw	b'00001111'	; 最終的に設定するプリスケール値 (1:128)を設定する
		movwf	OPTION_REG	;
		bcf		STATUS, RP0	; バンク0に切り替え

	;出力ポート初期化（０にする）
		bcf		SERVO
		bcf		LEDS
		bcf		LEDO
		;カウンタの初期化
		;ＤＩＲを１にして　CNT4を右位置へセット
		movlw	d'1'
		movwf	DIR
		movlw	MCNT
		movwf	CNT4
		decf	CNT4,f		;元の値-１処理
		;起動遅延フラグ1（遮断機が下りはじめる時間の遅延処理）の初期化
		movlw	d'0'
		movwf	delay_s

	;スイッチ押下チェック(ポート５のチェック）
		btfsc	GPIO,5		;GP5が0かチェック
		goto	delay_set	;1だったら
	;ポート５が０だったら動作遅延モードにする
		movlw	d'1'
		movwf	delay_f
	;ディレイ用カウンタ
		movlw	d'250'	;20ms*250 =約5秒
		movwf	CNT6
		movf	CNT6,W
		movwf	CNT7
		goto	main_loop
delay_set 
	;ディレイ用カウンタ
		movlw	d'100'
		movwf	CNT6
		movf	CNT6,W
		movwf	CNT7
		goto	main_loop
		
main_loop
	;ウオッチドッグタイマクリア
		clrwdt				; WDT　クリア

	;位置データをカウンタにセット
		movf	CNT4,w
		movwf	CNT3
	;パルス発生開始 1ms
		bsf		SERVO
		movlw	d'1'
		call	DLY_N
		movf	CNT4,w
		movwf	CNT3
P_LOOP
	;このループでホーン位置決定のための時間を調整
		nop
		decfsz	CNT3,f
		goto	P_LOOP
		bcf		SERVO ;パルス終わり

	;残りのパルスサイクル時間生成（20ms-2msの時間）
		movlw	d'18'
		call	DLY_N


BT_CHK
	;スイッチ押下チェック(ポート４のチェック）
		btfss	GPIO,4		;GP4が１かチェック
		goto	ROT_LEFT	;0だったら
		goto	ROT_RIGHT

ROT_RIGHT 
	;右回転処理
		;LED消灯
		bcf		LEDO
		bcf		LEDS

		incf	CNT4,f		;+１する
		movf	CNT4,w		;ワークレジスタにセット
		movwf	CNT5		;ワークレジスタの値をcnt5に保管
		movlw	MCNT		;上限値をワークレジスタにセット
		subwf	CNT5,w		;CNT5とワークレジスタを引き算して
		btfss	STATUS,Z	;０かどうか判断（０の場合は指定した上限値）
		goto	main_loop	;切り替え時にＬＥＤを双方点灯させないとき
		decf	CNT4,f		;元の値-１処理
		;Max値を超えた場合、ＤＩＲを１にセット
		movf	DIR,f		;ワークレジスタにセット
		btfss	STATUS,Z	;dirが０かチェック
		goto	main_loop	;dirが１ならループに戻る 
		movlw	d'1'
		movwf	DIR		;dirに１をセット
		movlw	d'0'
		movwf	delay_s		;遅延フラグ１
		goto	main_loop

ROT_LEFT
	;左回転処理
		bsf	LEDS
		;起動時の遅延処理
		movf	delay_s,f	;ワークレジスタにセット
		btfss	STATUS,Z	;遅延フラグが０かチェック
		goto	ROT_LEFT2	;フラグが１なら回転処理へ 
		;遅延ループ(フラグが０の場合）
		;サーボのサイクルが20msとして2秒遅延させるばあい１００回メインへループさせる
		decfsz	CNT7,f
		goto	main_loop
		;カウンタを初期値に戻してフラグに１をセット
		movf	CNT6,w
		movwf	CNT7
		movlw	d'1'
		movwf	delay_s		;遅延フラグ１

ROT_LEFT2
		;降りるスピード調整（ループ２回に1回とする）
		movf	delay_c,f		;ワークレジスタにセット
		btfss	STATUS,Z	;動作遅延フラグが０かチェック
		goto	delayc
		movlw	d'1'
		movwf	delay_c		;動作遅延フラグ
		;降りる処理
		decfsz	CNT4,f		;-1して０か判断して
		goto	main_loop	;０以外のとき（切り替え時にＬＥＤを双方点灯させないとき）
		incf	CNT4,f		;０の時は+1する
		movf	DIR,f		;DIRが０かチェック
		btfsc	STATUS,Z	;1かチェック（zフラグの判断）
		goto	main_loop
		movlw	d'0'
		movwf	DIR			;dirに０をセット
		;遮断機が下りたらLED2を点灯
		bsf		LEDO
		goto	main_loop
delayc	
   		movlw	d'0'
		movwf	delay_c		;動作遅延フラグ
		goto	main_loop


DLY_N	;タイマールーチン
        ;ｃａｌｌ前にワークレジスタに値をセットしておくこと
		;NmS
		movwf	CNT1
DLP1	;1mS
		movlw	d'200'
		movwf	CNT2
DLP2
		nop
		nop
		decfsz	CNT2,f
		goto	DLP2
		decfsz	CNT1,f
		goto	DLP1
		return

		END