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
('A`)