;**********************************************************************
;                                                                     *
;    Filename:	    	Res1st.asm                                    *
;    Date:		Nov/24  2000                                  *
;    Author:		Atsushi Hirohata                              *
;    Company:		ALINCO INC                                    *
;**********************************************************************
;                                                                     *
;    Notes:   	XE708 N generator for Rescue Robot Contest            *
;                                                                     *
;**********************************************************************

	list      p=16c621a          ; list directive to define processor
	#include <p16c621a.inc>      ; processor specific variable definitions

	__CONFIG   _CP_OFF & _WDT_OFF & _BODEN_OFF & _PWRTE_ON & _RC_OSC

; '__CONFIG' directive is used to embed configuration data within .asm file.
; The lables following the directive are located in the respective .inc file. 
; See respective data sheet for additional information on configuration word.



;***** VARIABLE DEFINITIONS
;------ バイト定義 ------
A_REGI		EQU	0x20
X_REGI		EQU	0x21
Y_REGI		EQU	0x22
RCOUNT		EQU	0x23
SDATAZ		EQU	0x24
SDATA1		EQU	0x25
SDATA2		EQU	0x26
w_temp        	EQU     0x27        	; variable used for context saving 
STATUS_temp   	EQU     0x28        	; variable used for context saving
CHDATA		EQU	0x29		;CH設定の比較 前回設定時の値
IF_N_2		EQU	0x2A		; N値の固定部分
;
;----- アドレス ------
URAMTOP0	EQU	0x20		;USER領域の開始点
URAMBOTM0	EQU	0x6F		;USER領域の終了点
;
;---PORT B----
PCLK		EQU	0		;PLL CLOCKの出力
PDATA		EQU	1		;PLL DATAのの出力
PSTB		EQU	2		;PLL ENABLE出力
PTTOUT		EQU	3		;ユニットのPTT入力へ
PTTIN		EQU	4		;送信の検出
CS		EQU	5		;受信信号の検出（Lで信号あり、送信禁止）
INH		EQU	6		;送信禁止状態であることの出力 Hで禁止
TXPOW		EQU	7		;送信パワー（Lでパワーが出る状態）
;
;----- 定数定義 ------
OP_0		EQU	B'00000101'	;オプション DATA
OP_1		EQU	B'00110110'
OP_2		EQU	B'11000100'	;LSB
;
IF_R_0		EQU	B'00000110'	; レファレンスDATA
IF_R_1		EQU	B'00000011'
IF_R_2		EQU	B'01010010'	; LSB
;
IF_N_0		EQU	B'00000000'
IF_N_1		EQU	B'01111111'
;
TIME_20MS	EQU	.256-.78	; TIMERの値

;
;**********************************************************************
	ORG     0x000             	; processor reset vector
  	goto    POWER_ON         	; go to beginning of program
	ORG     0x004             	; interrupt vector location
	goto 	INTERRUPT_HANDLER
;
;--------------------------------
;	POWER ON PROCESS
;--------------------------------
POWER_ON
	call	PORT_INIT		; ポート初期化
	call	URAM_INIT		; ユーザーRAM初期化
	call	SET_PLL_N		; PLL N値設定
	
	movlw	TIME_20MS
	movwf	TMR0
	bcf	INTCON,T0IF		; タイマ0のリクエストフラグのクリア
	bsf	INTCON,T0IE		; タイマ0のインターラプト設定
	bcf	INTCON,RBIF		; RB4〜7の状態変化割込みフラグのクリア
	bsf	INTCON,RBIE		; RB4の状態変化割込み設定	
	bsf	INTCON,GIE		; マスタ割込み許可
;
;--------------------------------
;	MAIN (アイドル）
;--------------------------------
MAIN
	goto	MAIN
;
;--------------------------------
;	ポート初期化
;--------------------------------
PORT_INIT
	movlw	B'00000000'   		;INITCON設定  割込み禁止
	movwf	INTCON
	
	movlw	0x07
	movwf	CMCON
;	
	bsf	STATUS,RP0		; bank1に設定
	
	movlw	B'00000101'
	movwf	OPTION_REG
	movlw	B'00011111'	
	movwf	TRISA			; ポートAはすべて入力
;	
	movlw	B'00110000'		; CSとPTTINを入力とする
	movwf	TRISB			; ポートBの設定
	bcf	STATUS,RP0		; bank0に戻る
;
	movlw	B'11001000'		; portの出力設定 受信状態､INHIBIT状態
	movwf	PORTB
;
	return
;	
;--------------------------------
;	ユーザーRAM初期化
;--------------------------------
URAM_INIT
	movlw	URAMTOP0
	movwf	FSR
;
UINIT_1
	clrf	INDF
	incf	FSR,F
	movfw	FSR
	sublw	URAMBOTM0+1
	bnz	UINIT_1
;	
	return
;	
;	
;--------------------------------
;	PLL N値設定
;--------------------------------
SET_PLL_N
	bsf	PORTB,INH	;CH設定中はINHを立てておく
	
	movf	PORTA,w		; CHDATAを呼び出し
	movwf	CHDATA		; 設定chをCHDATAに記憶
	sublw	B'10000011'
	btfsc	CHDATA,4	; 10CH以上であれば次の命令無視
	addlw	.6
	movwf	IF_N_2
	
	movlw	OP_0		; OPTIONの設定
	movwf	SDATAZ
	movlw	OP_1
	movwf	SDATA1
	movlw	OP_2
	movwf	SDATA2
	call	SDATA_SSOUT
;	
	movlw	IF_R_0		; レファレンスの設定
	movwf	SDATAZ
	movlw	IF_R_1
	movwf	SDATA1
	movlw	IF_R_2
	movwf	SDATA2
	call	SDATA_SSOUT
;

	movlw	IF_N_0		; N値の設定
	movwf	SDATAZ
	movlw	IF_N_1
	movwf	SDATA1
	movfw	IF_N_2
	movwf	SDATA2
	call	SDATA_SSOUT
;	
	btfsc	PORTB,CS
	bcf	PORTB,INH	;CSがH（信号無し）であればINHIBITを解除する
	return
;
;--------------------------------
;	SDATAシリアル出力
;--------------------------------
SDATA_SSOUT
	bcf	PORTB,PSTB	;ENABLE一旦落す
	bsf 	PORTB,PSTB	;ENABLEの立ち上げ
;
	movlw	SDATAZ
	movwf	X_REGI		; 8bit中の位置
	movlw	.2		; シリアルの先頭アドレス 5bit無効
	movwf	Y_REGI		; 8bitのDATAの順番
	movlw	.3		; 3回送る設定
	movwf	RCOUNT		; 
;
	call	SSOUT
;
	bcf	PORTB,PSTB	; ENABLEをLOWに戻す
;
	return
;
SSOUT
	movfw	X_REGI		
	movwf	FSR
	movfw	INDF
	movwf	A_REGI
	
	movfw	Y_REGI
	sublw	.7
	btfsc	STATUS,2	; 
	goto	SSOUT_7		; ７番目であれば

	movfw	Y_REGI
	sublw	.6
	btfsc	STATUS,2
	goto	SSOUT_6		; 6番目であれば

	movfw	Y_REGI
	sublw	.5
	btfsc	STATUS,2
	goto	SSOUT_5

	movfw	Y_REGI
	sublw	.4
	btfsc	STATUS,2
	goto	SSOUT_4
	
	movfw	Y_REGI
	sublw	.3
	btfsc	STATUS,2
	goto	SSOUT_3
	
	movfw	Y_REGI
	sublw	.2
	btfsc	STATUS,2
	goto	SSOUT_2	

	movfw	Y_REGI
	sublw	.1
	btfsc	STATUS,2
	goto	SSOUT_1
;	
	rlf	A_REGI,F
SSOUT_1
	rlf	A_REGI,F
SSOUT_2
	rlf	A_REGI,F
SSOUT_3
	rlf	A_REGI,F
SSOUT_4
	rlf	A_REGI,F
SSOUT_5
	rlf	A_REGI,F
SSOUT_6
	rlf	A_REGI,F
SSOUT_7
	incf	Y_REGI,F
SSOUT_8
	rlf	A_REGI,F
	btfsc	STATUS,0	;キャリーが立てば	
	goto	SSOUT_9		; 1 の出力
	bcf	PORTB,PDATA	;立たなければ
	goto	SSOUT_10	; 0 の出力

SSOUT_9
	bsf	PORTB,PDATA

SSOUT_10
	bsf	PORTB,PCLK	; クロックをH
	nop
	nop
	nop
	bcf	PORTB,PCLK	; クロックを L
	decf	Y_REGI,F
	btfss	STATUS,2	; Y_REGIが０になるまでDATAを繰り返す
	goto	SSOUT_8
	
	incf	X_REGI,F	;なればX_REGIを1個増やす
	movlw	.8
	movwf	Y_REGI		;Y_REGIを８に戻す
	incf	FSR,F
	movfw	INDF
	movwf	A_REGI
	decf	RCOUNT,F	;RCOUNTが0になるまで続ける
	btfss	STATUS,2
	goto	SSOUT_8
	
	bcf	PORTB,PDATA	;DATA bitを0に戻す
		
	return



;**************************************************
;	割込み処理
;	TIMER0	PTT
;***************************************************
INTERRUPT_HANDLER
		movwf   w_temp            ; save off current W register contents
		swapf	STATUS,w          ; move STATUS register into W register
		movwf	STATUS_temp       ; save off contents of STATUS register
;
		btfss	PORTB,PTTIN	;
		goto	TX_INT		; 送信中､開始の割込み(PTTIN=L) TXINTへ飛ぶ

;
;<<<<<<<<<<<<<<<<<<<<PTTIN受信時の割込み>>>>>>>>>>>>>>>>>>>>>>>		

RX_INT
		btfss	INTCON,T0IF	;TIMER0のリクエストでないなら		
		goto	RX_SET
;
;    	-------	CH監視の割込みと判断  ------------
		bcf	INTCON,T0IF	;TIMER0のクリア
		call	CH_COMPAIR	;TIMER0のリクエストならチャンネル比較する
		movlw	TIME_20MS
		movwf	TMR0
		goto	I_H_EXIT
		
;		
;	-------- CSまたは送信から受信へ変化したと判断 -------
RX_SET
		bcf	INTCON,RBIF	;ポート変化割込みフラグのクリア

		bsf	INTCON,T0IE
		btfsc	PORTB,PTTOUT
		goto	RX_SET_EXIT	; PTTOUTがHならなにもしない
		

;	    ---- 送信から受信へ変化したと判断 ------
		bsf	PORTB,TXPOW	; LならHに戻す
		bsf	PORTB,PTTOUT	; 送信から受信へ戻す処理
		bcf	INTCON,T0IF	;TIMER0のクリア
		movlw	TIME_20MS
		movwf	TMR0
		bsf	INTCON,T0IE	; 受信タイマーの開始
;
;	CSの監視でINHの設定 受信割込み事はいつでも
RX_SET_EXIT
		btfsc	PORTB,CS	;CSがHなら
		bcf	PORTB,INH	;INHをLOW
		btfss	PORTB,CS	;CSがLなら
		bsf	PORTB,INH	;INHをHigh
		goto	I_H_EXIT
		
;
;<<<<<<<<<<<<<<<<<PTTIN 送信時の割込み>>>>>>>>>>>>>>>>>>>>>>>>>>>
TX_INT
		btfss	INTCON,T0IF	;TIMER0のリクエストでないなら
		goto	CS_INT

;	----送信状態になってから20ms後のTXPOWの処理----
		bcf	INTCON,T0IF	;TIMER0フラグのクリア
		bcf	INTCON,T0IE	;完全送信状態はタイマーを使わない	
		bcf	PORTB,PTTOUT	;送信状態にする（駄目押し）
		bcf	PORTB,TXPOW	;TXPOWを落す
		bcf	PORTB,INH	;INHIBIT解禁
		goto	I_H_EXIT
;		
;	---- CSまたは受信から送信変化の割込み--------
CS_INT
		bcf	INTCON,RBIF	;ポート変化割込みフラグのクリア
		bsf	PORTB,INH	;INHIBITを立てる
		btfsc	PORTB,CS	
		goto	TX_TIMER_SET	;CSがH（受信信号なし)なら送信処理開始

		btfss	PORTB,PTTIN	;
		bcf	INTCON,T0IE	;CSがLならタイマを禁止
		bsf	PORTB,PTTOUT	;PTTOUTを受信状態に
		goto	I_H_EXIT

;	    ------ 送信開始処理OK ------------		
TX_TIMER_SET
		bcf	PORTB,PTTOUT	;ユニットの送信開始
		bcf	INTCON,T0IF
		movlw	TIME_20MS
		movwf	TMR0			
		bsf	INTCON,T0IE	;TIMER0の設定　送信タイマー待ち	
;		
I_H_EXIT	
		swapf   STATUS_temp,w     ; retrieve copy of STATUS re*gister
		movwf	STATUS            ; restore pre-isr STATUS register contents
		swapf   w_temp,f
		swapf   w_temp,w          ; restore pre-isr W register contents

		retfie                    ; return from interrupt

;--------------------------------
;	受信中のチャンネル比較
;--------------------------------
CH_COMPAIR
		movf	CHDATA,w
		subwf	PORTA,w	
		btfss	STATUS,2	
		CALL    SET_PLL_N	;チャンネル設定に変化があれば N設定
		return
;

		END                       ; directive 'end of program'
