tab が変だけど…


;
; PS/2キーボードからキーコードを読み取り
; LCDに表示してみる
;
;                                      2001/11/22 作成
;                                      2001/11/25 更新
;
; 秋月アセンブラ用



;              ----__----
;       RA2 1-|*         |-18 RA1
;       RA3 2-|          |-17 RA0
; RA4 TOCKI 3-|          |-16 OSC1 CLKIN
;     /MCLR 4-|          |-15 OSC2 CLKOUT
;       Vss 5-| PIC16C84 |-14 Vdd
;   RB0 INT 6-|          |-13 RB7
;       RB1 7-|          |-12 RB6
;       RB2 8-|          |-11 RB5
;       RB3 9-|          |-10 RB4
;              ----------

;	I/Oポートの割り当て
; PORT A
LCD_E		equ		0	; RA0 - LCD E
LCD_RS		equ		1	; RA1 - LCD RS
X68_READY	equ		2	; RA2 - X68 KY READY
;						  RA3 - 未使用 (入力に設定し、GNDへ接続)
;						  RA4 - 未使用 (入力に設定し、GNDへ接続)

; PORT B
PS2_CLK		equ		0	; RB0 - PS/2 CLK  (外部にプルアップ抵抗をつける 2kくらい?)
PS2_DATA	equ		1	; RB1 - PS/2 DATA (外部にプルアップ抵抗をつける 2kくらい?)
X68_RxD		equ		2	; RB2 - X68 KY RxD
X68_TxD		equ		3	; RB3 - X68 KY TxD
LCD_DB4		equ		4	; RB4 - LCD DB4
LCD_DB5		equ		5	; RB5 - LCD DB5
LCD_DB6		equ		6	; RB6 - LCD DB6
LCD_DB7		equ		7	; RB7 - LCD DB7

;	LCDの余ったピンの処理
;	LCD DB0  - GND
;	LCD DB1  - GND
;	LCD DB2  - GND
;	LCD DB3  - GND
;	LCD R/~W - GND 常時ライト


	.16c84				; デバイスの設定(省略できません)
	
	.osc	HS			; 発振タイプの設定
						; LP	ローパワー発振子(〜約200kHz)
						; HS	高速クリスタル(約4MHz〜20MHz)
						; RC	RC発振
						; XT	クリスタル・セラロック(〜約4MHz)

	.wdt	off			; ウォッチドックタイマの有効・無効の設定
						; 省略時は“on”
						
	.pwrt	on			; パワーアップタイマの有効・無効の設定
	
	.protect	off		; プロテクトの設定
						; “on”にすると、その IC からプログラムを読み出す事が
						; 出来なくなる
						; 省略時は“off”

;	eedata	{value[,value..]}	; データ EEPROM の初期値をセットする
								; この命令を使用することで、プログラムの
								; 書き込みと同時にデータ EEPROM の内容を
								; 書き込む事が出来る
								; (PIC16x84 のみ有効)

;	eeorg	{value}		; データ EEPROMのアセンブラ内部アドレスをセットする
						; (eedata 命令で書き込むアドレスをセットする)
						; (PIC16x84 のみ有効)

; -----------------------------------------------------------------------------

;	システムレジスタにラベル付け

TMR0		equ		01h		; タイマ(BANK0)
PCL			equ		02h		; プログラムカウンタの下位8ビット(BANK0)

STATUS		equ		03h		; ステータスレジスタ(BANK0)
C			equ		0		; STATUS,C   キャリーフラグ
DC			equ		1		; STATUS,DC  DCフラグ
Z			equ		2		; STATUS,Z   ゼロフラグ
PD			equ		3		; STATUS,PD  パワーダウンフラグ
TO			equ		4		; STATUS,TO  タイムアウトフラグ
RP0			equ		5		; STATUS,RP0 RAMのバンク切り替え

PORTA		equ		05h		; I/OポートA(BANK0)
PORTB		equ		06h		; I/OポートB(BANK0)

INTCON		equ		0bh		; 割り込み制御レジスタ(BANK0)
RBIF		equ		0		; RB<4:7>ポートチェンジ割り込みフラグ
INTF		equ		1		; INT(RA4)割り込みフラグ
T0IF		equ		2		; TMR0オーバーフロー割り込みフラグ
RBIE		equ		3		; RBIF割り込み許可
INTE		equ		4		; INTF割り込み許可
T0IE		equ		5		; TMR0割り込み許可
EEIE		equ		6		; データEEPROM書き込み終了割り込み許可
GIE			equ		7		; 全体割り込み許可

OPTION		equ		01h		; オプションレジスタ(BANK1)
RBPU		equ		7		; OPTION,RBPU ポートBのプルアップ 0:行う 1:行わない

TRISA		equ		05h		; ポートA出力/入力設定 0:出力 1:入力(BANK1)
TRISB		equ		06h		; ポートB出力/入力設定 0:出力 1:入力(BANK1)

;	定数のセット
;	PICの動作クロックに応じて書き換えてください

CONST_WAIT_MS	equ		250	; ms 単位のウェイト用定数
							; CONST_WAIT_MS = (動作クロック[MHz]/4)*100
							; 10MHz 時 250
							;  8MHz 時 222
							;  6MHz 時 150


; -----------------------------------------------------------------------------

;	変数を宣言
		org		0ch
temp1				ds		1	; 0ch から 1 バイト分のメモリを確保し、
								; ラベル“temp1”を付ける(変数temp1)汎用一時変数
temp2				ds		1	; 汎用一時変数
lcd_temp1			ds		1	; LCD表示で使う変数
lcd_temp2			ds		1	; LCD表示で使う変数
lcd_temp3			ds		1	; LCD表示で使う変数
lcd_temp4			ds		1	; LCD表示で使う変数
wait_count1			ds		1	; ウェイトルーチンで使うカウンタ
wait_count2			ds		1	; ウェイトルーチンで使うカウンタ
ps2txd				ds		1	; 送信バッファ
ps2rxd				ds		1	; 受信バッファ
ps2count			ds		1	; PS/2通信処理で使うカウンタ
ps2parity			ds		1	; PS/2通信のパリティ計算用
com_status			ds		1	; 通信ステータスフラグ
x68receiving		equ		0	; com_status,x68receiving	受信中
x68transmitrq		equ		1	; com_status,x68transmitrq	送信要求
x68rxdvalid			equ		2	; com_status,x68rxdvalid	受信データ有効
ps2rxdvalid			equ		3	; com_status,ps2rxdvalid	受信データ有効
ps2rxdfound			equ		4	; com_status,ps2rxdfound	データを見つけた

; -----------------------------------------------------------------------------
; -----------------------------------------------------------------------------

;	リセット処理

		org		000h

		goto	start





; -----------------------------------------------------------------------------
; -----------------------------------------------------------------------------

;	割り込み処理

		org		004h
		retfie





; -----------------------------------------------------------------------------
; -----------------------------------------------------------------------------

;	初期設定いろいろ

start
		bsf		STATUS,RP0	; bank1

;	I/Oポートの設定
;	ポートA
		movlw	11111000b	; w=11111000b
		;		   ||||+----- LCD_E			out
		;		   |||+------ LCD_RS		out
		;		   ||+------- X68_READY		out
		;		   |+-------- RA3 - 未使用	in
		;		   +--------- RA4 - 未使用	in
		movwf	TRISA		; 設定レジスタに書き込み

;	ポートB
		movlw	00000100b	;
		;		|||||||+----- PC_DATA		out
		;		||||||+------ PC_CLK		out
		;		|||||+------- X68_RxD		in
		;		||||+-------- X68_TxD		out
		;		|||+--------- LCD_DB4		out
		;		||+---------- LCD_DB5		out
		;		|+----------- LCD_DB6		out
		;		+------------ LCD_DB7		out
		movwf	TRISB		; 設定レジスタに書き込み

		bcf		STATUS,RP0	; bank0

;	PS/2 のCLKは0にしておく(データ送出禁止)
		movlw	11111110b		; PS/2KEY データ送出禁止
		movwf	PORTB

;	変数の初期化

		clrf	com_status

;	LCDの初期化

		movlw	15
		call	wait			; 15ms 待つ

		bcf		PORTA,LCD_RS	;  RS DB7 DB6 DB5 DB4
		movlw	00110000b		;  0   0   0   1   1
		call	lcd_write4

		movlw	5
		call	wait			; 5ms 待つ

		movlw	00110000b
		call	lcd_write4

		movlw	1
		call	wait			; 1ms 待つ

		movlw	00110000b
		call	lcd_write4

		movlw	00100000b		;  DB7 DB6 DB5 DB4
		call	lcd_write4		;   0   0   1   0
								; 4ビットモードに設定

		movlw	00101000b		; 4bit, 1/16duty, 5x7
		call	lcd_write

		movlw	00000001b		; 表示クリア
		call	lcd_write

		movlw	2				; クリアには少し時間がかかるので
		call	wait			; 2ms 待つ

		movlw	00000110b		; エントリーモードセット
		call	lcd_write		; (カーソルの進み方の設定)

		movlw	00001110b		; 表示オン/オフコントロール
		call	lcd_write		; 表示オン, カーソル表示あり, ブリンクなし




; -----------------------------------------------------------------------------



		call	read
		movf	ps2rxd,0		; 何か受信したら
		call	disp_h			; 表示してみる(Power On Self Test Passed を受信する)
;		movlw	5
;		call	wait			; (表示しない場合は wait が必要のようだ)

		movlw	0edh			; Set Status LED
		call	ps2transmit
		movlw	5
		call	wait

		call	read
		movf	ps2rxd,0		; 何か受信したら
		call	disp_h			; 表示してみる (ack が帰ってくる)

		movlw	00000010b
		call	ps2transmit		; NumLock ランプを点灯

loop
		call	read
		movf	ps2rxd,0		; 何か受信したら
		call	disp_h			; 表示してみる
		goto	loop

read
		call	ps2receive		; 聞き耳を立てる
		btfss	com_status,ps2rxdvalid
		goto	read
		return



; -----------------------------------------------------------------------------
; -----------------------------------------------------------------------------

;	受信処理
;	受信すべきデータがを見つけたら com_status,ps2rxdfound をセット
;	正常に受信すると com_status,ps2rxdvalid セットし
;	ps2rxd に受信データをいれて帰ってくる

;	エラー(com_status,ps2rxdvalid が 0)の場合
;	com_status,ps2rxdfound が 0 なら受信すべきデータが無かった。
;	1 なら 受信動作を行ったが、パリティエラーかフレーミングエラーが発生した


ps2receive
		bcf		com_status,ps2rxdvalid	; データ有効フラグをクリア
		bcf		com_status,ps2rxdfound
		movlw	11111111b			; PS/2KEY データ送出許可
		movwf	PORTB
		btfsc	PORTB,PS2_CLK
		return						; CLK がHなら終了
;	スタートビットの取り込み
ps2receive_startbit
		btfsc	PORTB,PS2_DATA		; スタートビットと思われるところが
		goto	ps2receive_error	; 1だったらエラー
ps2receive_wait0
		call	ps2wait_h			; CLK がHになるまで待つ
		movlw	1
		movwf	ps2parity			;パリティ計算用変数を初期化
;		clrf	ps2rxd				; 受信の準備、バッファをクリア
		movlw	8
		movwf	ps2count			; count=8

;	8ビット分データを取り込む
ps2receive_data
		call	ps2wait_l			; CLK がLになるまで待つ
		rrf		ps2rxd,1
		btfsc	PORTB,PS2_DATA		; データを取り込む
		goto	ps2receive_b1
ps2receive_b0
		bcf		ps2rxd,7
		goto	ps2receive_wait1
ps2receive_b1
		bsf		ps2rxd,7
		incf	ps2parity,1			; parity+1
ps2receive_wait1
		call	ps2wait_h			; CLK がHになるまで待つ
		decfsz	ps2count,1	; count-1
		goto	ps2receive_data

;	パリティビットの取り込み
ps2receive_parity
		call	ps2wait_l			; CLK がLになるまで待つ
		movlw	00000001b
		andwf	ps2parity,1			; ps2parity のbit0のみ取り出し
		btfsc	PORTB,PS2_DATA
		goto	ps2receive_parity1
ps2receive_parity0
		movf	ps2parity,1
		btfss	STATUS,Z
		goto	ps2receive_error	; パリティエラー
		goto	ps2receive_parity_end
ps2receive_parity1
		movf	ps2parity,1
		btfsc	STATUS,Z
		goto	ps2receive_error	; パリティエラー
		goto	ps2receive_parity_end
ps2receive_parity_end
		call	ps2wait_h			; CLK がHになるまで待つ

;	ストップビットの取り込み
ps2receive_stopbit
		call	ps2wait_l			; CLK がLになるまで待つ
		btfss	PORTB,PS2_DATA		; ストップビットと思われるところが
		goto	ps2receive_error	; 0だったらエラー
;	受信終了
		goto	ps2receive_end

ps2receive_error
;	受信動作したけれどエラーでした
		bcf		com_status,ps2rxdvalid
		bsf		com_status,ps2rxdfound
		return

ps2receive_end
		movlw	11111110b		; PS/2KEY データ送出禁止
		movwf	PORTB
		bsf		com_status,ps2rxdvalid	; データ有効フラグをセット
		bsf		com_status,ps2rxdfound
		return



;-----------------------------------------------------------------------------
;	送信処理
;	wレジスタにデータを入れてコールすると
;	PS/2キーボードへ向けて送信する

ps2transmit
		movwf	ps2txd
		movlw	1
		movwf	ps2parity	;パリティ計算用変数を初期化
		movlw	8
		movwf	ps2count	; count=8

ps2transmit_startbit
		movlw	11111101b		; スタートビットをセット
		movwf	PORTB

ps2transmit_data
		call	ps2wait_l			; CLK がLになるまで待つ
		btfsc	ps2txd,0			; データをセット
		goto	ps2transmit_data1
ps2transmit_data0
		movlw	11111101b
		movwf	PORTB
		goto	ps2transmit_wait1
ps2transmit_data1
		movlw	11111111b
		movwf	PORTB
		incf	ps2parity,1			; parity+1
ps2transmit_wait1
		call	ps2wait_h			; CLK がHになるまで待つ
		rrf		ps2txd,1			; 右シフト
		decfsz	ps2count,1	; count-1
		goto	ps2transmit_data

ps2transmit_parity
		call	ps2wait_l			; CLK がLになるまで待つ
		btfsc	ps2parity,0			; パリティをセット
		goto	ps2transmit_parity1
ps2transmit_parity0
		movlw	11111101b
		movwf	PORTB
		goto	ps2transmit_wait2
ps2transmit_parity1
		movlw	11111111b
		movwf	PORTB
ps2transmit_wait2
		call	ps2wait_h			; CLK がHになるまで待つ

ps2transmit_stopbit
		call	ps2wait_l			; CLK がLになるまで待つ
		movlw	11111111b
		movwf	PORTB				; ストップビットをセット
		call	ps2wait_h			; CLK がHになるまで待つ
		call	ps2wait_l			; CLK がLになるまで待つ
		call	ps2wait_h			; CLK がHになるまで待つ

;	送信おしまい
		movlw	11111110b		; PS/2KEY データ送出禁止
		movwf	PORTB
		return





ps2wait_h
		btfss	PORTB,PS2_CLK		; CLK がHになるまで待つ
		goto	ps2wait_h
		return
ps2wait_l
		btfsc	PORTB,PS2_CLK		; CLK がLになるまで待つ
		goto	ps2wait_l
		return




; -----------------------------------------------------------------------------
; -----------------------------------------------------------------------------

; wレジスタの内容を16進表記で表示する


; 例
;	1:	movlw		0ah		; w=0ah
;	2:	call	disp_h
; と実行するとLCDに
;	+----------------+
;	|0A_             |
;	|                |
;	+----------------+ と表示する

disp_h
		movwf	lcd_temp3		; lcd_temp3=w
		clrf	lcd_temp4		; lcd_temp5=0

		bsf		PORTA,LCD_RS	; RS を 1

disp_h_loop
		swapf	lcd_temp3,0

		andlw	00001111b
		movwf	lcd_temp1		; lcd_temp1=w

		addlw	6				; w=w+6
		btfsc	STATUS,DC		; 0fhを超えた(w=9以下)
		goto	disp_h_1

;	0〜9の時
		movlw	030h			; w=030h
		addwf	lcd_temp1,0		; w=w+lcd_temp1
		call	lcd_write
		goto disp_h_2

;	a〜hの時
disp_h_1
		movlw	037h			; w=037h
		addwf	lcd_temp1,0		; w=w+lcd_temp1
		call	lcd_write

disp_h_2
		btfsc	lcd_temp4,0		; lcd_temp4のbit0が 0以外ならreturn
		return					;

		decf	lcd_temp4,1		; lcd_temp4=lcd_temp4-1 (0-1=0ffh)
		swapf	lcd_temp3,1
		goto	disp_h_loop





; -----------------------------------------------------------------------------
; -----------------------------------------------------------------------------

;	LCDへの書き込み
;	wレジスタの内容をLCDに書き込む


lcd_write
		movwf	lcd_temp1	; lcd_temp1=w
		call	lcd_write4	; 上位4ビットの書き込み

		swapf	lcd_temp1,0	; lcd_temp1 の上位4ビットと下位4ビットを入れ替えて
							; wレジスタに代入
		call	lcd_write4	; 下位4ビットの書き込み

		return


;
;	書き込みサブルーチンのサブルーチン
;	wレジスタの上位4ビットだけを書き込む

;	ポートBの下位4ビットは変化しない

lcd_write4
		andlw	11110000b	; w=w&11110000b
		movwf	lcd_temp2	; 書き込むデータの上位4ビットのみを退避

		movf	PORTB,0		; w=PORTB
		andlw	00001111b	; w=w&00001111b
							; ポートBの下位4ビットのみを取り出し

		iorwf	lcd_temp2,0	; w=w|lcd_temp2
		movwf	PORTB		; ボートBの下位4ビットとデータの上位4ビットを
							; 合成してポートBに出力

		bsf		PORTA,LCD_E	; 書き込み
		nop
		bcf		PORTA,LCD_E

		movlw	1
		call	wait		; 少し待つ

		return





; -----------------------------------------------------------------------------
; -----------------------------------------------------------------------------

;	wレジスタの値に応じて ms 単位のウェイトを入れる

;	使用変数
;		wait_count1,wait_count2

;	例、約2ms待つ
;	1:	movlw	2
;	2:	call	wait

;	メモ
;	使用クロックに応じて、定数 CONST_WAIT_MS を定義してください

;	CONST_WAIT_MS = (動作クロック[MHz]/4)*100

;	例、8Mhz時
;	CONST_WAIT_MS	equ	200

wait
		movwf	wait_count1		; wait_count1=w
wait_loop1
			movlw	CONST_WAIT_MS
			movwf	wait_count2		; wait_count2=CONST_WAIT_MS
wait_loop2
				nop
				nop
				nop
				nop
				nop
				nop
				nop
				decfsz	wait_count2,1	; wait_count2=wait_count2-1
				goto	wait_loop2		; if wait_count2!=0 goto wait_loop2
			decfsz	wait_count1,1	; wait_count1=wait_count1-1
			goto	wait_loop1		; if wait_count1!=0 goto wait_loop1
		return					; else return



webmaster@kyoutan.jpn.org

('A`)