; Tab width = 4

;----------------------------------------------------------------------------
; ** シリアル通信サンプル2 (データ受信) **
;
; ・シリアル通信ポートから受信した数値をLCDに表示する
;----------------------------------------------------------------------------
; 1.01 990208 SEGA Enterprises,LTD.
;----------------------------------------------------------------------------

chip	LC868700			; チップの種類をアセンブラに指定
world	external			; 外部メモリ用プログラム

public	main				; ghead.asm から参照されるシンボル

extern	_game_end			; アプリケーション終了


; **** システム定数の定義 ***************************************************

							; OCR(発振制御レジスタ)設定値
osc_rc		equ 04dh		;	システムクロックに内蔵RC発振を指定
osc_xt		equ 0efh		;	システムクロックに水晶発振を指定

LowBattChk	equ 06eh		; ローバッテリー検出フラグ(RAMバンク0)


; *** データセグメント ******************************************************

		dseg				; データセグメント開始

r0:		ds		1			; 間接アドレッシングレジスタ r0
r1:		ds		1			; 間接アドレッシングレジスタ r1
r2:		ds		1			; 間接アドレッシングレジスタ r2
r3:		ds		1			; 間接アドレッシングレジスタ r3
		ds		12			; その他のレジスタ

counter: ds		1			; カウンタ
work1:	ds		1			; 作業用(put2digitで使用)


; *** コードセグメント ******************************************************

		cseg				; コードセグメント開始

; *-------------------------------------------------------------------------*
; * ユーザープログラム														*
; *-------------------------------------------------------------------------*
main:
		call	cls			; LCD表示の消去
		call	BattChkOff	; ローバッテリー自動検出機能 OFF
		clr1	P3INT,0		; P3割り込みをマスク
cwait:
		call	SioInit		; シリアル通信の初期化
		bz		start		; VMS が接続されていればスタート

		ld		P3			; [M]ボタンチェック
		bn		acc,6,finish ; [M]ボタンが押されていたらアプリ終了

		jmp		cwait		; VMS が接続されるまで待機
start:

loop0:
		call	SioRecv1	; 1byte受信する
		bnz		next4		; 受信データがない場合はnext4へ

		ld		b			; 受信したデータをaccへ
		mov		#2,c		; 表示座標(水平)
		mov		#1,b		; 表示座標(垂直)
		call	put2digit	; LCDに2桁数値表示

next4:						; ** [M](モード)ボタンチェック **
		ld		P3
		bn		acc,6,finish ; [M]ボタンが押されていたらアプリ終了

		jmp		loop0		; 繰り返し

finish:						; ** アプリケーション終了処理 **
		call	SioEnd		; シリアル通信終了処理
		call	BattChkOn	; ローバッテリー自動検出機能 ON
		jmp		_game_end	; アプリケーション終了		

; *-------------------------------------------------------------------------*
; * シリアル通信の初期化													*
; * 出力: acc = 0   : 正常終了												*
; *       acc = 0ffh: VMS が接続されていない								*
; *-------------------------------------------------------------------------*
; シリアル通信の初期化
; システムクロックが水晶モードであることを前提としています。
SioInit:
							; **** VMS同士の接続を確認 ****
		ld		P7			; 接続状態の確認
		and		#%00001101	; P70, P72, P73 をチェック
		sub		#%00001000	; P70=0, P72=0, P73=1 か判定
		bz		next3		; 接続されているときnext3へ
	
		mov		#0ffh,acc	; 接続されていないとき acc=0ffh として異常終了
		ret					; SioInit終わり
next3:

							; **** シリアル通信の初期化 ****
		mov		#0,SCON0	; LSBを先頭に出力するよう指定
		mov		#0,SCON1	; LSBを先頭に入力するよう指定
		mov		#088h,SBR	; 転送レートを設定する
		clr1	P1,0		; P10ラッチをクリア(P10/SO0)
		clr1	P1,2		; P12ラッチをクリア(P12/SCK0)
		clr1	P1,3		; P13ラッチをクリア(P13/SO1)

		mov		#%00000101,P1FCR ; 端子機能設定
		mov		#%00000101,P1DDR ; 端子機能設定

		mov		#0,SBUF0	; 転送バッファクリア
		mov		#0,SBUF1	; 転送バッファクリア

		ret					; SioInit終わり


; *-------------------------------------------------------------------------*
; * シリアル通信の終了														*
; *-------------------------------------------------------------------------*
SioEnd:						; **** シリアル通信終了処理 ****

		mov		#0,SCON0	; SCON0 = 0
		mov		#0,	SCON1	; SCON1 = 0
		mov		#0bfh,P1FCR	; P1FCR = 0bfh
		mov		#0a4h,P1DDR	; P1DDR = 0a4h

		ret					; SioEnd終わり


; *-------------------------------------------------------------------------*
; * シリアルポートから1byte受信する											*
; *   出力 b: 受信データ													*
; *        acc=0   : 受信データあり											*
; *        acc=0ffh: 受信データなし											*
; *-------------------------------------------------------------------------*
SioRecv1:					; **** 1byte受信する ****
		ld		SCON1
		bp		acc,1,next5	; 受信データがあるときnext5へ
		bp		acc,3,next6 ; 現在転送中ならnext6へ
		
		set1	SCON1,3		; 転送開始
next6:
		mov		#0ffh,acc	; acc=0ffh(受信データなし)として帰る
		ret					; SioRecv1終わり		
next5:
		
		ld		SBUF1		; 受信データを読み込む
		st		b			; データをbへコピー
		
		clr1	SCON1,1		; 転送終了フラグをリセット
		
		mov		#0,acc		; acc=0(受信データあり)として帰る
		ret					; SioRecv1終わり


; *-------------------------------------------------------------------------*
; * 2桁の数値を表示する														*
; * 入力 acc : 数値															*
; *        c : 文字水平位置												  	*
; *        b : 文字垂直位置												  	*
; *-------------------------------------------------------------------------*
put2digit:
		push	b			; 座標データを退避
		push	c			;
		st		c			; 10の位と1の位の値をそれぞれ計算
		xor		a			; ( acc = acc/10, work1 = acc mod 10 )
		mov		#10,b		;
		div					;
		ld		b			;
		st		work1		; 1の位の計算結果をwork1に保存
		ld		c			;
		pop		c			; 座標値を(c.b)に復帰
		pop		b			; 
		push	b			; また退避
		push	c			;
		call	putch		; 10の位を表示
		ld		work1		; 1の位の値を読み込み
		pop		c			; 座標値を(c,b)に復帰
		pop		b			; 
		inc		c			; 表示座標を右へ
		call	putch		; 1の位を表示

		ret					; put2digit終わり


; *-------------------------------------------------------------------------*
; * LCD表示イメージを消去する												*
; *-------------------------------------------------------------------------*
cls:
		push	OCR			; OCR値を退避
		mov		#osc_rc,OCR ; システムクロックを指定

		mov		#0,XBNK		; 表示用RAMのバンクアドレスを指定(BANK0)
		call	cls_s		; そのバンク内のデータをクリア

		mov		#1,XBNK		; 表示用RAMのバンクアドレスを指定(BANK1)
		call	cls_s		; そのバンク内のデータをクリア
		pop		OCR			; OCR値を復帰
		
		ret					; cls終わり
		
cls_s:						; *** 表示用RAM 1BANK分の消去 ***
		mov		#80h,r2		; 間接アドレッシングレジスタを表示用RAMの先頭に
		mov		#80h,b 		; ループカウンタbにループ数をセット
loop3:
		mov		#0,@r2		; アドレスをインクリメントしながら0を書き込む
		inc		r2			;
		dbnz	b,loop3		; bが0になるまで繰り返す
		
		ret					; cls_s終わり
		

; *-------------------------------------------------------------------------*
; * 指定位置に1キャラクタ表示する											*
; * 入力 acc : キャラクタコード												*
; *        c : 文字水平位置												  	*
; *        b : 文字垂直位置												  	*
; *-------------------------------------------------------------------------*
putch:
		push	XBNK
		push	acc
		call	locate		; 座標から表示RAMのアドレスを計算
		pop		acc
		call	put_chara	; 1キャラクタ表示する
		pop		XBNK
		
		ret					; putch終わり
		

locate:	; **** 表示位置指定から表示用RAMのアドレスを計算 ****
		; ** 入力 c: 水平位置(0〜5) b: 垂直位置(0〜3)
		; ** 出力 r2: RAMアドレス XBNK: 表示用RAMバンク

							; *** 表示用RAMバンクアドレスの判断 ***
		ld		b			; b>=2 のとき next1 へ
		sub		#2			;
		bn		PSW,7,next1	;
		
		mov		#00h,XBNK	; 表示用RAMのバンクアドレスを指定(BANK0)
		br		next2
next1:
		st		b
		mov		#01h,XBNK	; 表示用RAMのバンクアドレスを指定(BANK1)
next2:

							; *** 表示指定位置のRAMアドレス計算 ***
		ld		b			; b * 40h + c + 80h
		rol					;
		rol					;
		rol					;
		rol					;
		rol					;
		rol					;
		add		c			;
		add		#80h		;
		st		r2			; RAMアドレスをr2に格納
				
		ret					; locate終わり


put_chara:
		push	PSW			; PSW値を退避
		set1	PSW,1		; データRAMバンク1を選択

							; *** キャラクタデータアドレスの計算 ***
		rol					; (TRH,TRL) = acc*8 + fontdata
		rol					;
		rol					;	
		add		#low(fontdata)	;
		st		TRL				;
		mov		#0,acc			;
		addc	#high(fontdata)	;
		st		TRH			;

		push	OCR			; OCR値を退避
		mov		#osc_rc,OCR ; システムクロックを指定

		mov		#0,b		; キャラクタデータ読み出し用オフセット値
		mov		#4,c		; ループカウンタ
loop1:
		ld		b			; 1ライン目の表示データを読み出す
		ldc					;
		inc		b			; 読み出しデータのオフセットを +1
		st		@r2			; 表示データを表示用RAMに転送
		ld		r2			; 表示用RAMアドレス +6
		add		#6			;
		st		r2			;

		ld		b			; 2ライン目の表示データを読み出す
		ldc					;
		inc		b			; 読み出しデータのオフセットを +1
		st		@r2			; 表示データを表示用RAMに転送
		ld		r2			; 表示用RAMアドレス +10
		add		#10			;
		st		r2			;
		
		dec		c			; ループカウンタのデクリメント
		ld		c			; 
		bnz		loop1		; 8ライン分(4回)繰り返し
		
		pop		OCR			; OCR値を復帰
		pop		PSW			; PSW値を復帰

		ret					; put_chara終わり


; *-------------------------------------------------------------------------*
; * キャラクタのビットイメージデータ										*
; *-------------------------------------------------------------------------*
fontdata:
		db 07ch, 0e6h, 0c6h, 0c6h, 0c6h, 0ceh, 07ch, 000h	;'0' 00 
		db 018h, 038h, 018h, 018h, 018h, 018h, 03ch, 000h	;'1' 01
		db 07ch, 0c6h, 0c6h, 00ch, 038h, 060h, 0feh, 000h	;'2' 02
		db 07ch, 0e6h, 006h, 01ch, 006h, 0e6h, 07ch, 000h	;'3' 03
		db 00ch, 01ch, 03ch, 06ch, 0cch, 0feh, 00ch, 000h	;'4' 04
		db 0feh, 0c0h, 0fch, 006h, 006h, 0c6h, 07ch, 000h	;'5' 05
		db 01ch, 030h, 060h, 0fch, 0c6h, 0c6h, 07ch, 000h	;'6' 06
		db 0feh, 0c6h, 004h, 00ch, 018h, 018h, 038h, 000h	;'7' 07
		db 07ch, 0c6h, 0c6h, 07ch, 0c6h, 0c6h, 07ch, 000h	;'8' 08
		db 07ch, 0c6h, 0c6h, 07eh, 006h, 00ch, 078h, 000h	;'9' 09		


; *-------------------------------------------------------------------------*
; *	ローバッテリー自動検出機能 ON											*
; *-------------------------------------------------------------------------*
BattChkOn:
		push	PSW			; PSW値を退避

		clr1	PSW,1		; データRAMバンク0を選択
		mov		#0,acc		; ローバッテリー検出をする(0)
		st		LowBattChk	; ローバッテリー自動検出フラグ(RAMバンク0)

		pop		PSW			; PSW値を復帰
		ret					; BattChkOn終わり


; *-------------------------------------------------------------------------*
; *	ローバッテリー自動検出機能 OFF											*
; *-------------------------------------------------------------------------*
BattChkOff:
		push	PSW			; PSW値を退避

		clr1	PSW,1		; データRAMバンク0を選択
		mov		#0ffh,acc	; ローバッテリー検出をしない(0ffh)
		st		LowBattChk	; ローバッテリー自動検出フラグ(RAMバンク0)

		pop		PSW			; PSW値を復帰
		ret					; BattChkOff終わり

