;---------------- Rally Game (tennis like) ----------------

  	INCLUDE"p16F84A.inc"
	list p=16F84A

	__CONFIG _HS_OSC & _WDT_OFF & _PWRTE_OFF & _CP_OFF


; Define file reg -----------------------------------------
Memory		EQU	0x0C
DX		EQU	Memory+0	; "DX" File Register for LCD
DXX		EQU	Memory+1	; "DXX" File Register for LCD

TMP1		EQU	Memory+2	; File Register for temporary
TMP2		EQU	Memory+3	; File Register for temporary

TIME1		EQU	Memory+4	; using "wait_ms" routine
TIME2		EQU	Memory+5	; using "wait_ms" routine

CUR1 		EQU	Memory+6	; Initial position of LCD line 1
CUR2		EQU	Memory+7	; Initial position of LCD line 2


CH_BALL		equ	Memory + d'10'	; Chara code of ball
CH_RACKET_L	equ	Memory + d'11'	; Chara code of left racket
CH_RACKET_R	equ	Memory + d'12'	; Chara code of right racket
CH_SPACE	equ	Memory + d'13'	; Chara code of space


BP_INIT_L	equ	Memory + d'20'
BP_INIT_R	equ	Memory + d'21'
BALL_POS	equ	Memory + d'22'
RKT_L_POS	equ	Memory + d'23'
RKT_R_POS	equ	Memory + d'24'
RLY_CNT_POS	equ	Memory + d'25'


DIR_BALL	equ	Memory + d'30'	; direction of ball (IF 0bit=0 THEN right ELSE left)
SAVE_W		equ	Memory + d'31'	; save W reg
SAVE_STS	equ	Memory + d'32'	; save status flag
RET_BEGIN	equ	Memory + d'33'	; return BEGIN
CURR_CUR1	equ	Memory + d'34'	; current cursor position (line 1)
CURR_CUR2	equ	Memory + d'35'	; current cursor position (line 2)
GAME_STATUS	equ	Memory + d'36'	; game status (0bit:GameOver?, 1bit:..., )
RALLY_CNT	equ	Memory + d'37'	; rally count
QUE_SW2_ST	equ	Memory + d'38'	; queue status of switch 2
QUE_SW3_ST	equ	Memory + d'39'	; queue status of switch 3


BALL_SPEED	equ	Memory + d'40'	; ball speed




; Start up routine ----------------------------------------
	org	0
	goto	START
	org	4
	; Execute interrupt routine -----------------------
	movwf	SAVE_W		; save W reg
	swapf	STATUS,0	; swap STATUS reg to W reg
	movwf	SAVE_STS	; save STATUS reg
	
	movlw	b'00010000'
	movwf	INTCON
	
	call	IntrpFunc	; Interrupt routine
	
	movlw	b'10010000'
	movwf	INTCON
	
	swapf	SAVE_STS,0
	movwf	STATUS
	swapf	SAVE_W,1
	swapf	SAVE_W,0
	
	retfie
	; End interrupt -----------------------------------

;----------------------------------------------------------
; Main routine --------------------------------------------
START
	; Settting
	call		SetUp
	CALL		ini_lcd		; Initialization
	call		StartScrn	; Display title
	call		InitGame
	
	; wait to push SW1
BEGIN	btfsc		RET_BEGIN,0
	goto		BEGIN
	
	; Main Loop ------------------------------------
M_LOOP	btfsc		RET_BEGIN,0
	goto		BEGIN
	
	; move ball
	call		MoveBall
	
	; is game over ?
	btfsc		GAME_STATUS,0
	goto		END_M_LOOP
	
	;btfss		PORTB,0		;IF RB0 = 1 THEN skip next line
	;call		OnSwitch1    	;           ELSE CALL MOV1
	
	
	; check switch 2
CHK_SW2	btfss		PORTB,1		;IF RB1 = 1 THEN skip next line
	goto		ON_SW2
	goto		OFF_SW2
	
ON_SW2	call		OnSwitch2	;           ELSE call ON switch2
	goto		CHK_SW3
	
OFF_SW2	call		OffSwitch2
	
	
	; check switch 3
CHK_SW3	btfss		PORTB,2		;IF RB2 = 1 THEN skip next line
	goto		ON_SW3
	goto		OFF_SW3
	
ON_SW3	call		OnSwitch3	;           ELSE call ON switch3
	goto		M_STEP
	
OFF_SW3	call		OffSwitch3
	
	
M_STEP
	; Display rally count
	call		DspRallyCnt
	
	; waiting...
	;movlw		d'44';D'300'
	;call		wait_ms
	call		StepInterval
	
	
	; erase part
	btfsc		QUE_SW2_ST,0
	call		ErsRktL
	
	btfsc		QUE_SW3_ST,0
	call		ErsRktR
	
	goto		M_LOOP
	
END_M_LOOP
	call		GameOverScrn
	goto		START
	
; End main routine ----------------------------------------
;----------------------------------------------------------



; Interrupt routine ---------------------------------------
IntrpFunc
	btfss		RET_BEGIN,0
	goto		INTRP_BGN0
	
	btfsc		RET_BEGIN,0
	goto		INTRP_BGN1
	
INTRP_BGN0
	bsf		RET_BEGIN,0
	goto		INTRP_END
	
INTRP_BGN1
	bcf		RET_BEGIN,0

INTRP_END
	return



; Set up main program -------------------------------------
SetUp
	movlw		0x6f		; Chara Code [ball]
	movwf		CH_BALL
	
	movlw		0x29		; Chara code [racket left]
	movwf		CH_RACKET_L
	
	movlw		0x28		; Chara code [racket right]
	movwf		CH_RACKET_R
	
	movlw		0x20
	movwf		CH_SPACE
	
	movlw		b'10000000'
	movwf		CUR1		;Cursor position(1st line)
	movlw		b'11000000'
	movwf		CUR2		;Cursor position(2nd line)
	
	; Port Setting ------------------------------------
	BSF		STATUS, RP0	;selection of Bank1
	MOVLW		0x00
	MOVWF		TRISA		;PORTA: output
	MOVLW		B'00000111'
	MOVWF		TRISB		;RB0-2: input, RB3-7: output
	
	movlw		b'10010000'
	movwf		INTCON
	movlw		b'00000000'
	movwf		OPTION_REG
	
	BCF		STATUS, RP0	;selection of Bank0
	;--------------------------------------------------
	return



; Start screen --------------------------------------------
StartScrn
	call		DspTitle	; Display title
	
	movlw		d'18'		; TMP1 = loop count + 1
	movwf		TMP1
	
SS_LOOP
	decfsz		TMP1,1
	goto		SS_WAIT
	goto		SS_END
	
SS_WAIT
	movlw		d'255'
	call		wait_ms
	goto		SS_LOOP
	
SS_END
	call		ErsTitle	; Erase title
	return

; Display title -------------------------------------------
DspTitle
	; Line 1
	movf		CUR1,0
	movwf		CURR_CUR1
	call		SetMode
	movlw		0x52		; 'R'
	call		PutChar
	
	incf		CURR_CUR1,1
	movf		CURR_CUR1,0
	call		SetMode
	movlw		0x61		; 'a'
	call		PutChar
	
	incf		CURR_CUR1,1
	movf		CURR_CUR1,0
	call		SetMode
	movlw		0x6C		; 'l'
	call		PutChar
	
	incf		CURR_CUR1,1
	movf		CURR_CUR1,0
	call		SetMode
	movlw		0x6C		; 'l'
	call		PutChar
	
	incf		CURR_CUR1,1
	movf		CURR_CUR1,0
	call		SetMode
	movlw		0x79		; 'y'
	call		PutChar
	
	incf		CURR_CUR1,1
	movf		CURR_CUR1,0
	call		SetMode
	movf		CH_SPACE,0
	call		PutChar
	
	incf		CURR_CUR1,1
	movf		CURR_CUR1,0
	call		SetMode
	movlw		0x47		; 'G'
	call		PutChar
	
	incf		CURR_CUR1,1
	movf		CURR_CUR1,0
	call		SetMode
	movlw		0x61		; 'a'
	call		PutChar
	
	incf		CURR_CUR1,1
	movf		CURR_CUR1,0
	call		SetMode
	movlw		0x6D		; 'm'
	call		PutChar
	
	incf		CURR_CUR1,1
	movf		CURR_CUR1,0
	call		SetMode
	movlw		0x65		; 'e'
	call		PutChar
	
	; Line 2
	movf		CUR2,0
	movwf		CURR_CUR2
	call		SetMode
	movlw		0x53		; 'S'
	call		PutChar
	
	incf		CURR_CUR2,1
	movf		CURR_CUR2,0
	call		SetMode
	movlw		0x57		; 'W'
	call		PutChar
	
	incf		CURR_CUR2,1
	movf		CURR_CUR2,0
	call		SetMode
	movlw		0x31		; '1'
	call		PutChar
	
	incf		CURR_CUR2,1
	movf		CURR_CUR2,0
	call		SetMode
	movlw		0x7E		; '[right arrowhead]'
	call		PutChar
	
	incf		CURR_CUR2,1
	movf		CURR_CUR2,0
	call		SetMode
	movlw		0x53		; 'S'
	call		PutChar
	
	incf		CURR_CUR2,1
	movf		CURR_CUR2,0
	call		SetMode
	movlw		0x74		; 't'
	call		PutChar
	
	incf		CURR_CUR2,1
	movf		CURR_CUR2,0
	call		SetMode
	movlw		0x61		; 'a'
	call		PutChar
	
	incf		CURR_CUR2,1
	movf		CURR_CUR2,0
	call		SetMode
	movlw		0x72		; 'r'
	call		PutChar
	
	incf		CURR_CUR2,1
	movf		CURR_CUR2,0
	call		SetMode
	movlw		0x74		; 't'
	call		PutChar
	
	incf		CURR_CUR2,1
	movf		CURR_CUR2,0
	call		SetMode
	movlw		0x2F		; '/'
	call		PutChar
	
	incf		CURR_CUR2,1
	movf		CURR_CUR2,0
	call		SetMode
	movlw		0x53		; 'S'
	call		PutChar
	
	incf		CURR_CUR2,1
	movf		CURR_CUR2,0
	call		SetMode
	movlw		0x74		; 't'
	call		PutChar
	
	incf		CURR_CUR2,1
	movf		CURR_CUR2,0
	call		SetMode
	movlw		0x6F		; 'o'
	call		PutChar
	
	incf		CURR_CUR2,1
	movf		CURR_CUR2,0
	call		SetMode
	movlw		0x70		; 'p'
	call		PutChar
	
	return

; Erase title -------------------------------------------
ErsTitle
	movf		CUR1,0
	movwf		CURR_CUR1
	call		SetMode
	movf		CH_SPACE,0
	call		PutChar
	
	incf		CURR_CUR1,1
	movf		CURR_CUR1,0
	call		SetMode
	movf		CH_SPACE,0
	call		PutChar
	
	incf		CURR_CUR1,1
	movf		CURR_CUR1,0
	call		SetMode
	movf		CH_SPACE,0
	call		PutChar
	
	incf		CURR_CUR1,1
	movf		CURR_CUR1,0
	call		SetMode
	movf		CH_SPACE,0
	call		PutChar
	
	incf		CURR_CUR1,1
	movf		CURR_CUR1,0
	call		SetMode
	movf		CH_SPACE,0
	call		PutChar
	
	incf		CURR_CUR1,1
	movf		CURR_CUR1,0
	call		SetMode
	movf		CH_SPACE,0
	call		PutChar
	
	incf		CURR_CUR1,1
	movf		CURR_CUR1,0
	call		SetMode
	movf		CH_SPACE,0
	call		PutChar
	
	incf		CURR_CUR1,1
	movf		CURR_CUR1,0
	call		SetMode
	movf		CH_SPACE,0
	call		PutChar
	
	incf		CURR_CUR1,1
	movf		CURR_CUR1,0
	call		SetMode
	movf		CH_SPACE,0
	call		PutChar
	
	incf		CURR_CUR1,1
	movf		CURR_CUR1,0
	call		SetMode
	movf		CH_SPACE,0
	call		PutChar
	
	; Line 2
	movf		CUR2,0
	movwf		CURR_CUR2
	call		SetMode
	movf		CH_SPACE,0
	call		PutChar
	
	incf		CURR_CUR2,1
	movf		CURR_CUR2,0
	call		SetMode
	movf		CH_SPACE,0
	call		PutChar
	
	incf		CURR_CUR2,1
	movf		CURR_CUR2,0
	call		SetMode
	movf		CH_SPACE,0
	call		PutChar
	
	incf		CURR_CUR2,1
	movf		CURR_CUR2,0
	call		SetMode
	movf		CH_SPACE,0
	call		PutChar
	
	incf		CURR_CUR2,1
	movf		CURR_CUR2,0
	call		SetMode
	movf		CH_SPACE,0
	call		PutChar
	
	incf		CURR_CUR2,1
	movf		CURR_CUR2,0
	call		SetMode
	movf		CH_SPACE,0
	call		PutChar
	
	incf		CURR_CUR2,1
	movf		CURR_CUR2,0
	call		SetMode
	movf		CH_SPACE,0
	call		PutChar
	
	incf		CURR_CUR2,1
	movf		CURR_CUR2,0
	call		SetMode
	movf		CH_SPACE,0
	call		PutChar
	
	incf		CURR_CUR2,1
	movf		CURR_CUR2,0
	call		SetMode
	movf		CH_SPACE,0
	call		PutChar
	
	incf		CURR_CUR2,1
	movf		CURR_CUR2,0
	call		SetMode
	movf		CH_SPACE,0
	call		PutChar
	
	incf		CURR_CUR2,1
	movf		CURR_CUR2,0
	call		SetMode
	movf		CH_SPACE,0
	call		PutChar
	
	incf		CURR_CUR2,1
	movf		CURR_CUR2,0
	call		SetMode
	movf		CH_SPACE,0
	call		PutChar
	
	incf		CURR_CUR2,1
	movf		CURR_CUR2,0
	call		SetMode
	movf		CH_SPACE,0
	call		PutChar
	
	incf		CURR_CUR2,1
	movf		CURR_CUR2,0
	call		SetMode
	movf		CH_SPACE,0
	call		PutChar
	
	return



; Display game over screen --------------------------------
GameOverScrn
	call		DspGameOver	; Display "Game Over"
	
	movlw		d'10'		; TMP1 = loop count + 1
	movwf		TMP1
	
GOS_LOOP
	decfsz		TMP1,1
	goto		GOS_WAIT
	goto		GOS_END
	
GOS_WAIT
	movlw		d'255'
	call		wait_ms
	goto		GOS_LOOP
	
GOS_END
	call		ErsGameOver	; Erase "Game Over"
	
	return

; Display "Game Over" -------------------------------------
DspGameOver
	movf		CUR1,0
	movwf		CURR_CUR1
	call		SetMode
	movlw		0x47		; 'G'
	call		PutChar
	
	incf		CURR_CUR1,1
	movf		CURR_CUR1,0
	call		SetMode
	movlw		0x61		; 'a'
	call		PutChar
	
	incf		CURR_CUR1,1
	movf		CURR_CUR1,0
	call		SetMode
	movlw		0x6D		; 'm'
	call		PutChar
	
	incf		CURR_CUR1,1
	movf		CURR_CUR1,0
	call		SetMode
	movlw		0x65		; 'e'
	call		PutChar
	
	incf		CURR_CUR1,1
	movf		CURR_CUR1,0
	call		SetMode
	movf		CH_SPACE,0
	call		PutChar
	
	incf		CURR_CUR1,1
	movf		CURR_CUR1,0
	call		SetMode
	movlw		0x4F		; 'O'
	call		PutChar
	
	incf		CURR_CUR1,1
	movf		CURR_CUR1,0
	call		SetMode
	movlw		0x76		; 'v'
	call		PutChar
	
	incf		CURR_CUR1,1
	movf		CURR_CUR1,0
	call		SetMode
	movlw		0x65		; 'e'
	call		PutChar
	
	incf		CURR_CUR1,1
	movf		CURR_CUR1,0
	call		SetMode
	movlw		0x72		; 'r'
	call		PutChar
	
	return

; Erase "Game Over" ---------------------------------------
ErsGameOver
	movf		CUR1,0
	movwf		CURR_CUR1
	call		SetMode
	movlw		CH_SPACE
	call		PutChar
	
	incf		CURR_CUR1,1
	movf		CURR_CUR1,0
	call		SetMode
	movf		CH_SPACE,0
	call		PutChar
	
	incf		CURR_CUR1,1
	movf		CURR_CUR1,0
	call		SetMode
	movf		CH_SPACE,0
	call		PutChar
	
	incf		CURR_CUR1,1
	movf		CURR_CUR1,0
	call		SetMode
	movf		CH_SPACE,0
	call		PutChar
	
	incf		CURR_CUR1,1
	movf		CURR_CUR1,0
	call		SetMode
	movf		CH_SPACE,0
	call		PutChar
	
	incf		CURR_CUR1,1
	movf		CURR_CUR1,0
	call		SetMode
	movf		CH_SPACE,0
	call		PutChar
	
	incf		CURR_CUR1,1
	movf		CURR_CUR1,0
	call		SetMode
	movf		CH_SPACE,0
	call		PutChar
	
	incf		CURR_CUR1,1
	movf		CURR_CUR1,0
	call		SetMode
	movf		CH_SPACE,0
	call		PutChar
	
	incf		CURR_CUR1,1
	movf		CURR_CUR1,0
	call		SetMode
	movf		CH_SPACE,0
	call		PutChar
	
	return



; Initialize game -----------------------------------------
InitGame
	; Set racket position
	MOVF		CUR1,0
	movwf		RKT_L_POS
	addlw		d'15'
	movwf		RKT_R_POS
	
	; Set initial position of ball
	movf		CUR1,0
	addlw		d'1'
	movwf		BALL_POS	; Current position
	movwf		BP_INIT_L	; Initial position [left]
	addlw		d'13'
	movwf		BP_INIT_R	; Initial position [right]
	
	; Set initial position of rally count
	movf		CUR2,0
	addlw		d'6'
	movwf		RLY_CNT_POS
	
	; Set initial direction of ball
	clrf		DIR_BALL	; initial direction : right(=0)
	
	; Set return label BEGIN
	bsf		RET_BEGIN,0
	
	; Set game begin
	bcf		GAME_STATUS,0
	
	; initialize rally count
	clrf		RALLY_CNT
	
	; initialze queue
	clrf		QUE_SW2_ST
	clrf		QUE_SW3_ST
	
	; initialize ball speed
	call		SetBallSpd0	; fastest
	
	
	; Display
	call		DspBall
	call		DspRktL
	call		DspRktR
	call		DspItmCnt
	
	return

; Display parts -------------------------------------------
DspBall
	movf		BALL_POS,0
	call		SetMode
	movf		CH_BALL,0
	call		PutChar
	return

DspRktL
	movf		RKT_L_POS,0
	call		SetMode
	movf		CH_RACKET_L,0
	call		PutChar
	return

DspRktR
	movf		RKT_R_POS,0
	call		SetMode
	movf		CH_RACKET_R,0
	call		PutChar
	return

ErsRktL
	movf		RKT_L_POS,0
	call		SetMode
	movf		CH_SPACE,0
	call		PutChar
	return

ErsRktR
	movf		RKT_R_POS,0
	call		SetMode
	movf		CH_SPACE,0
	call		PutChar
	return

DspItmCnt
	movf		CUR2,0
	movwf		CURR_CUR2
	call		SetMode
	movlw		0x43		; 'C'
	call		PutChar
	
	incf		CURR_CUR2,1
	movf		CURR_CUR2,0
	call		SetMode
	movlw		0x6F		; 'o'
	call		PutChar
	
	incf		CURR_CUR2,1
	movf		CURR_CUR2,0
	call		SetMode
	movlw		0x75		; 'u'
	call		PutChar
	
	incf		CURR_CUR2,1
	movf		CURR_CUR2,0
	call		SetMode
	movlw		0x6E		; 'n'
	call		PutChar
	
	incf		CURR_CUR2,1
	movf		CURR_CUR2,0
	call		SetMode
	movlw		0x74		; 't'
	call		PutChar
	
	incf		CURR_CUR2,1
	movf		CURR_CUR2,0
	call		SetMode
	movlw		0x3A		; ':'
	call		PutChar
	
	return


; Move ball -----------------------------------------------
MoveBall
	; Erase
	movf		BALL_POS,0
	call		SetMode
	movf		CH_SPACE,0
	call		PutChar
	
	; New position
	btfss		DIR_BALL,0
	incf		BALL_POS,1
	btfsc		DIR_BALL,0
	decf		BALL_POS
	
	; Display
	call		DspBall
	
	; Judge shot error
	call		JdgShotErr
	
	return

; Judge shot error ----------------------------------------------
JdgShotErr
	movf		BALL_POS,0
	movwf		TMP1		; copy current BALL_POS
	
	movf		CUR1,0		; copy CUR1 to W reg
	
	bcf		STATUS,2	; clear Zero flag
	subwf		TMP1,1		; f = f - w
	
	btfsc		STATUS,2
	bsf		GAME_STATUS,0	; Game over...
	
	movlw		d'15'
	subwf		TMP1,1		; f = f - w
	
	btfsc		STATUS,2
	bsf		GAME_STATUS,0	; Game over...
	
	return


; ON switch2 ----------------------------------------------
OnSwitch2
	; check long push
	rlf		QUE_SW2_ST,1
	bsf		QUE_SW2_ST,0	; set 0bit
	movf		QUE_SW2_ST,0	; copy to W reg
	andlw		b'00000111'	; d'7'
	bcf		STATUS,2	; clear Zero flag
	sublw		d'7'
	btfsc		STATUS,2	; IF 2bit==0 THEN skip next line
	goto		END_ON_SW2
	
	; formal operation
	call		DspRktL		; Display left racket
	
	movf		BALL_POS,0
	movwf		TMP1		; copy current BALL_POS
	
	movf		CUR1,0
	
	subwf		TMP1,1		; f = f - w
	
	decfsz		TMP1,1		; IF --f == 0 THEN skip next line
	goto		END_ON_SW2
	
	; hit !
	bcf		DIR_BALL,0	; direction of ball (right)
	call		IncRallyCnt	; increment rally count
	
	; change ball speed
	movf		QUE_SW2_ST,0
	call		ChgBallSpd
	
END_ON_SW2
	return


; OFF switch 2 --------------------------------------------
OffSwitch2
	; enqueue
	rlf		QUE_SW2_ST,1
	bcf		QUE_SW2_ST,0	; set 0bit
	return


; ON switch3 ----------------------------------------------
OnSwitch3
	; check long push
	rlf		QUE_SW3_ST,1
	bsf		QUE_SW3_ST,0	; set 0bit
	movf		QUE_SW3_ST,0	; copy to W reg
	andlw		b'00000111'	; d'7'
	bcf		STATUS,2	; clear Zero flag
	sublw		d'7'
	btfsc		STATUS,2	; IF 2bit==0 THEN skip next line
	goto		END_ON_SW3
	
	; formal operation
	call		DspRktR		; Display right racket
	
	movf		BALL_POS,0
	movwf		TMP1		; copy current BALL_POS
	
	movf		CUR1,0
	addlw		d'15'		; end point of line 1
	
	subwf		TMP1,1		; f = f - w
	
	incfsz		TMP1,1
	goto		END_ON_SW3
	
	; hit !
	bsf		DIR_BALL,0	; direction of ball (left)
	
	; change ball speed
	movf		QUE_SW3_ST,0
	call		ChgBallSpd
	
END_ON_SW3
	return

; OFF switch 3 --------------------------------------------
OffSwitch3
	; enqueue
	rlf		QUE_SW3_ST,1
	bcf		QUE_SW3_ST,0	; set 0bit
	return


; Change ball speed ---------------------------------------
ChgBallSpd
	movwf		TMP1
	btfsc		TMP1,1
	goto		CBS_SPD1
	goto		CBS_SPD0
	
CBS_SPD1
	call		SetBallSpd1
	goto		END_CBS
	
CBS_SPD0
	call		SetBallSpd0
	
END_CBS
	return


; Set ball speed ------------------------------------------
SetBallSpd0
	clrf		BALL_SPEED
	bsf		BALL_SPEED,0
	return

SetBallSpd1
	clrf		BALL_SPEED
	bsf		BALL_SPEED,1
	return
	
	


; Increment rally count -----------------------------------
IncRallyCnt
	movf		RALLY_CNT,0
	andlw		0x0F
	
	bcf		STATUS,2
	sublw		d'9'
	
	btfss		STATUS,2
	goto		IRC_END
	
	; carry
	movlw		b'00010000'
	addwf		RALLY_CNT,1
	movlw		b'11110000'
	andwf		RALLY_CNT,1
	
IRC_END
	incf		RALLY_CNT,1
	
	return


; Display rally count -------------------------------------
DspRallyCnt
	
	movf		RLY_CNT_POS,0
	movwf		CURR_CUR2
	call		SetMode
	
	movf		RALLY_CNT,0
	movwf		TMP1
	rrf		TMP1,1
	rrf		TMP1,1
	rrf		TMP1,1
	rrf		TMP1,1
	movf		TMP1,0
	andlw		0x0F
	addlw		0x30		; Chara code '0'
	call		PutChar
	
	
	incf		CURR_CUR2,1
	movf		CURR_CUR2,0
	call		SetMode
	movf		RALLY_CNT,0
	andlw		0x0F
	addlw		0x30		; Chara code '0'
	call		PutChar
	
	return


; Step interval -------------------------------------------
StepInterval
	btfsc		BALL_SPEED,0
	goto		INTERVAL0
	btfsc		BALL_SPEED,1
	goto		INTERVAL1
	
INTERVAL0
	movlw		d'10';d'44'		; shortest
	goto		END_S_INTVL
	
INTERVAL1
	movlw		d'255'

END_S_INTVL
	call		wait_ms
	return



;//////////////////////////////////////////////////////////
; sub routines
;//////////////////////////////////////////////////////////

; Cursor Pos. Setting Mode --------------------------------
SetMode
	BCF		PORTA,1		;RS = 0 (LCD: Cursor position setting mode)
	MOVWF		DXX
	CALL		WR_LCD4
	RETURN


; Character Display Routine -------------------------------
PutChar
	BSF		PORTA,1		;RS =1 (LCD: Character writing mode)
	MOVWF		DXX
	CALL		WR_LCD4
	RETURN


WR_LCD8
	MOVF		DX,0		;LCD mode setting and character writing routine
	MOVWF		PORTB
	NOP
	BSF		PORTA,0
	NOP
	BCF		PORTA,0
	MOVLW		D'20'
	call		wait_ms
	RETURN

WR_LCD4
	MOVF		DXX,0
	MOVWF		DX
	CALL		WR_LCD8
	SWAPF		DX,1
	CALL		WR_LCD8
	RETURN

; Waiting -------------------------------------------------
wait_ms
	MOVWF		TIME1
STEPM	MOVLW		0xFF
	MOVWF		TIME2
STEPM1	MOVLW		0xFF
	DECFSZ		TIME2,1
	GOTO		STEPM1
	DECFSZ		TIME1,1
	GOTO		STEPM
	RETURN

; Initialize LCD ------------------------------------------
ini_lcd	
	MOVLW		D'255'
	call		wait_ms

	MOVLW		B'00000000'
	MOVWF		PORTA
	MOVLW		B'00110000'
	MOVWF		DX
	CALL		WR_LCD8
	MOVLW		D'255'
	call		wait_ms

	MOVLW		B'00110000'
	MOVWF		DX
	CALL		WR_LCD8
	MOVLW		D'255'
	call		wait_ms

	MOVLW		B'00110000'
	MOVWF		DX
	CALL		WR_LCD8
	
	MOVLW		B'00100000'
	MOVWF		DX
	CALL		WR_LCD8

	MOVLW		B'00101000'
	MOVWF		DXX
	CALL		WR_LCD4

	MOVLW		B'00000001'
	MOVWF		DXX
	CALL		WR_LCD4
	MOVLW		D'255'
	call		wait_ms

	MOVLW		B'00000110'
	MOVWF		DXX
	CALL		WR_LCD4

	MOVLW		B'00001110'
	MOVWF		DXX
	CALL		WR_LCD4

	RETURN

	END
