tab が変だけど…
;
; X68000のキーボードを
; AT互換機のPS/2ポートにつなぐのです
;
; 2001/11/26 作成
; 2001/11/27 更新
;
; 秋月アセンブラ(PA.EXE)用
; ----__----
; 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 ; 発振タイプの設定
.wdt off ; ウォッチドックタイマの有効・無効の設定
.pwrt on ; パワーアップタイマの有効・無効の設定
.protect off ; プロテクトの設定
; -----------------------------------------------------------------------------
; システムレジスタにラベル付け
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)
PCLATH equ 0ah ; プログラムカウンタの上位
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
CONST_WAIT_US equ 8 ; 10μs 単位のウェイト用定数
; CONST_WAIT_US = 10/(1/動作クロック[MHz]*4*3)
CONST_COMSPEED equ 130 ; シリアル通信用割り込み間隔
; CONST_COMSPEED = 255 - (osc[Hz] / bps / 32)+5?
; -----------------------------------------------------------------------------
; 変数を宣言
org 0ch
temp1 ds 1
status_led ds 1 ; ステータスLED状態保持
SCRLK equ 1
NUMLK equ 2
CAPSLK equ 3
lastdata ds 1 ; PS/2ポートに前回送出したデータ
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 ; ウェイトルーチンで使うカウンタ
int_w ds 1 ; 割り込み処理でのレジスタ退避用
int_status ds 1 ; 割り込み処理でのレジスタ退避用
x68txd ds 1 ; 送信バッファ
x68rxd ds 1 ; 受信バッファ
int_x68rmode ds 1 ; 受信処理内部状態
int_x68rcount ds 1 ; 受信割り込みカウンタ
int_x68tmode ds 1 ; 送信処理内部状態
int_x68tcount ds 1 ; 送信割り込みカウンタ
ps2txd ds 1 ; 送信バッファ
ps2rxd ds 1 ; 受信バッファ
ps2parity ds 1 ; パリティ計算用
ps2count ds 1 ; カウンタ
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 データを見つけた
ps2break equ 5 ; com_status,ps2break 通信中断
; -----------------------------------------------------------------------------
; -----------------------------------------------------------------------------
; リセット処理
org 000h
goto start
; -----------------------------------------------------------------------------
; -----------------------------------------------------------------------------
; 割り込み処理
org 004h
interrupt
movwf int_w ; wレジスタを退避
movf STATUS,0
movwf int_status ; ステータスレジスタを退避
movlw CONST_COMSPEED
movwf TMR0 ; TMR0プリセット
; -----------------------------------------------------------------------------
; x68キーボードとの通信処理
; 2400bps,8ビット,ストップビット1,パリティなし
; 受信すると x68rxd にデータが入り
; キーレディ信号 PORTA,X68_READY を 0
; データ有効フラグ com_status,x68rxdvalid を 1 にセットする
; 受信処理中は 受信処理中フラグ com_status,x68receiving が 1 になる
; プログラムで受信データを引き受けたら、
; キーレディ信号 PORTA,X68_READY を 1
; にすることで、次のデータの受信を行う
; (PORTA,X68_READY を 1 にしなければ、キーボードが次のデータを送信してこない)
; 受信処理
movf int_x68rmode,0 ; 内部状態に応じて分岐
addwf PCL,1 ; PCL=PCL+int_x68rmode
goto int_x68rmode0 ; スタートビット検出処理
goto int_x68rmode1 ; 本当にスタートビット?
goto int_x68rmode2_9 ; データの受信1
goto int_x68rmode2_9 ; データの受信2
goto int_x68rmode2_9 ; データの受信3
goto int_x68rmode2_9 ; データの受信4
goto int_x68rmode2_9 ; データの受信5
goto int_x68rmode2_9 ; データの受信6
goto int_x68rmode2_9 ; データの受信7
goto int_x68rmode2_9 ; データの受信8
goto int_x68rmode10 ; 受信処理終わり
int_x68rmode0
btfsc PORTB,X68_RxD
goto int_x68rbreak ; スタートビットを確認せず 中断
; X68_RxDが0 スタートビットがきた
bsf com_status,x68receiving ; 受信中フラグセット
movlw 2
movwf int_x68rcount ; int_x68rcount=2
incf int_x68rmode,1 ; int_x68rmode=int_x68rmode+1=1
goto int_x68rend
int_x68rmode1
btfsc PORTB,X68_RxD
goto int_x68rbreak ; スタートビットを確認せず 中断
; スタートビットを確認した
decf int_x68rcount,1 ; int_x68rcount=int_x68rcount-1
btfss STATUS,Z
goto int_x68rend ; int_x68rcountがゼロでなければ終了
; 3回続けてスタートビットを確認したので受信処理に入る
movlw 4
movwf int_x68rcount ; int_x68rcount=4
incf int_x68rmode,1 ; int_x68rmode=int_x68rmode+1=2
bcf com_status,x68rxdvalid ; 受信データ有効フラグクリア
clrf x68rxd ; 受信バッファクリア
goto int_x68rend
int_x68rmode2_9
decf int_x68rcount,1 ; int_x68rcount=int_x68rcount-1
btfss STATUS,Z
goto int_x68rend ; int_x68rcountがゼロでなければ終了
; 実際の受信 (割り込みが4回発生するごとに1回実行される)
rrf x68rxd,1 ; 受信バッファを右シフト
btfsc PORTB,X68_RxD
bsf x68rxd,7 ; RxDが1なら受信バッファのbit7をセット
movlw 4
movwf int_x68rcount ; int_x68rcount=4
incf int_x68rmode,1 ; int_x68rmode=int_x68rmode+1
goto int_x68rend
int_x68rmode10
decf int_x68rcount,1 ; int_x68rcount=int_x68rcount-1
btfss STATUS,Z
goto int_x68rend ; int_x68rcountがゼロでなければ終了
btfss PORTB,X68_RxD
goto int_x68rbreak ; ストップビットを確認せず 中断
; 受信正常終了
bcf PORTA,X68_READY ;
bsf com_status,x68rxdvalid ; 受信データ有効フラグセット
; 受信異常終了
int_x68rbreak
bcf com_status,x68receiving ; 受信中処理フラグクリア
clrf int_x68rmode
clrf int_x68rcount
int_x68rend
; -----------------------------------------------------------------------------
; 送信処理
; x68txd にデータをセットして
; 送信要求フラグ com_status,x68transmitrq を 1 にすると
; 送信が開始される
; 送信が終了すると com_status,x68transmitrq が 0 になる
; 送信を開始する前に com_status,x68transmitrq が 0 であることを確認する必要あり
movf int_x68tmode,0 ; 内部状態に応じて分岐
addwf PCL,1 ; PCL=PCL+int_x68tmode
goto int_x68tmode0 ; スタートビットを送信
goto int_x68tmode1_8 ; 1ビット目を送信
goto int_x68tmode1_8 ; 2ビット目を送信
goto int_x68tmode1_8 ; 3ビット目を送信
goto int_x68tmode1_8 ; 4ビット目を送信
goto int_x68tmode1_8 ; 5ビット目を送信
goto int_x68tmode1_8 ; 6ビット目を送信
goto int_x68tmode1_8 ; 7ビット目を送信
goto int_x68tmode1_8 ; 8ビット目を送信
goto int_x68tmode9 ; ストップビットを送信
goto int_x68tmode10 ; 送信おわり
int_x68tmode0
btfss com_status,x68transmitrq
goto int_x68tend ; 送信要求フラグが0なら終了
movlw 4
movwf int_x68tcount ; int_x68tcount=4
incf int_x68tmode,1 ; int_x68tmode=int_x68tmode+1=1
bcf PORTB,X68_TxD ; スタートビット(0)を送信
goto int_x68tend
int_x68tmode1_8
decf int_x68tcount,1 ; int_x68tcount=int_x68tcount-1
btfss STATUS,Z
goto int_x68tend ; int_x68rcountがゼロでなければ終了
; 受信バッファの下位ビットから順に送信する
btfsc x68txd,0
goto intx68tmode1_8_1
intx68tmode1_8_0
bcf PORTB,X68_TxD ;送信バッファのbit0が0なら0を送信
goto intx68tmode1_8end
intx68tmode1_8_1
bsf PORTB,X68_TxD ;送信バッファのbit0が1なら1を送信
intx68tmode1_8end
rrf x68txd,1 ;送信バッファを右シフト
movlw 4
movwf int_x68tcount ; int_x68tcount=4
incf int_x68tmode,1 ; int_x68tmode=int_x68tmode+1
goto int_x68tend
int_x68tmode9
decf int_x68tcount,1 ; int_x68tcount=int_x68tcount-1
btfss STATUS,Z
goto int_x68tend ; int_x68rcountがゼロでなければ終了
bsf PORTB,X68_TxD ; ストップビット(1)を送信
movlw 4
movwf int_x68tcount ; int_x68tcount=4
incf int_x68tmode,1 ; int_x68tmode=int_x68tmode+1
goto int_x68tend
int_x68tmode10
decf int_x68tcount,1 ; int_x68tcount=int_x68tcount-1
btfss STATUS,Z
goto int_x68tend ; int_x68rcountがゼロでなければ終了
clrf int_x68tcount
clrf int_x68tmode
bcf com_status,x68transmitrq ; 送信が終わりましたの印
int_x68tend
; -----------------------------------------------------------------------------
; 割り込み処理の終了
int_return
bcf INTCON,T0IF ; TMR0オーバーフロー割り込みフラグをクリア
movf int_status,0
movwf STATUS ; ステータスレジスタを元に戻す
movf int_w,0 ; wレジスタを元に戻す
; goto interrupt
retfie ; 割り込みを許可してリターン
; -----------------------------------------------------------------------------
; -----------------------------------------------------------------------------
; 初期設定いろいろ
start
;******************************************************************************
; goto ps2init
bsf STATUS,RP0 ; bank1
movlw 11000000b ; プリスケーラを使用、分周比1:2
; |||||||+----- PS0 -+
; ||||||+------ PS1 +- プリスケーラ分周比
; |||||+------- PS2 -+
; ||||+-------- PSA プリスケーラ設定 0:TMR0 1:WDT
; |||+--------- RTE TMR0信号のエッジ 0:↑ 1:↓
; ||+---------- RTS TMR0信号のソース 0:内部 1:外部
; |+----------- INTEDG INT 割り込みのエッジ 0:↓ 1:↑
; +------------ /RBPU ポートBのプルアップ 0:行う 1:行わない
movwf OPTION
; 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
; X68キーボードデータ送出禁止
bcf PORTA,X68_READY
; 通信ポートを1にしておく
movlw 11111111b
movwf PORTB
; 変数の初期化
clrf int_x68rmode
clrf int_x68rcount
clrf int_x68tcount
clrf int_x68tmode
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 ; 表示オン, カーソル表示あり, ブリンクなし
; 割り込み許可
movlw 10100000b
movwf INTCON ; TMR0割り込み許可
; -----------------------------------------------------------------------------
; -----------------------------------------------------------------------------
; PS/2 キーボードとしての初期化処理
ps2init
movlw 11111111b
movwf PORTB
movlw 100
call wait
ps2init1
btfss PORTB,PS2_CLK ; CLKがHになるまで待つ
goto ps2init1
ps2init2
btfss PORTB,PS2_DATA
goto main ; DATA がLなら受信処理
movlw 0aah
call ps2transmit ; セルフテストOK送信
btfsc com_status,ps2break
goto ps2init1 ; 送信が中断されたらもう一回
; -----------------------------------------------------------------------------
; -----------------------------------------------------------------------------
main
; X68キーボードデータ送出許可
bsf PORTA,X68_READY
; ホストコマンドの処理
hostcommand
call ps2receive
btfss com_status,ps2rxdvalid
goto main_keyin ; 受信しなければキー入力処理
; -----------------------------------------------------------------------------
set_status_led
movlw 0edh
subwf ps2rxd,0
btfss STATUS,Z
goto echo
movlw 0fah
call ps2transmit ; ACK
set_status_led_1
call ps2receive
btfss com_status,ps2rxdvalid
goto set_status_led_1
movlw 11111111b
movwf status_led
btfsc ps2rxd,0
bcf status_led,SCRLK
btfsc ps2rxd,1
bcf status_led,NUMLK
btfsc ps2rxd,2
bcf status_led,CAPSLK
set_status_led_2
btfsc com_status,x68transmitrq ; キーボードへ送信処理中なら
goto set_status_led_2 ; 終わるまで待つ
movf status_led,0
movwf x68txd
bsf com_status,x68transmitrq ; LEDの状態をキーボードへ送信
movlw 0fah
call ps2transmit ; ACK
goto main_keyin
; -----------------------------------------------------------------------------
echo
movlw 0eeh
subwf ps2rxd,0
btfss STATUS,Z
goto set_scancode
echo_1
movlw 0eeh
call ps2transmit
goto main_keyin
; -----------------------------------------------------------------------------
set_scancode
movlw 0f0h
subwf ps2rxd,0
btfss STATUS,Z
goto set_repeatrate
movlw 0fah
call ps2transmit ; ACK
set_scancode1
call ps2receive
btfss com_status,ps2rxdvalid
goto set_scancode1
movlw 002h
subwf ps2rxd,0
btfss STATUS,Z
goto set_scancode2
movlw 0fah
call ps2transmit ; ACK
goto main_keyin
set_scancode2
movlw 002h ; スキャンコードは
call ps2transmit ; 02のみ対応なので02と返す
goto main_keyin
; -----------------------------------------------------------------------------
set_repeatrate
movlw 0f3h
subwf ps2rxd,0
btfss STATUS,Z
goto keyboard_enable
movlw 0fah
call ps2transmit ; ACK
set_repeatrate1
call ps2receive
btfss com_status,ps2rxdvalid
goto set_repeatrate1
;***************************************
movlw 0fah
call ps2transmit ; ACK
goto main_keyin
; -----------------------------------------------------------------------------
keyboard_enable
movlw 0f4h
subwf ps2rxd,0
btfss STATUS,Z
goto keyboard_disable
movlw 0fah
call ps2transmit ; ACK
keyboard_enable1
;***************************************
goto main_keyin
; -----------------------------------------------------------------------------
keyboard_disable
movlw 0f5h
subwf ps2rxd,0
btfss STATUS,Z
goto resend
movlw 0fah
call ps2transmit ; ACK
keyboard_disable1
;***************************************
goto main_keyin
; -----------------------------------------------------------------------------
resend
movlw 0f5h
subwf ps2rxd,0
btfss STATUS,Z
goto reset
resend1
movf lastdata,0
call ps2transmit ; resend
goto main_keyin
; -----------------------------------------------------------------------------
reset
movlw 0f5h
subwf ps2rxd,0
btfss STATUS,Z
goto unknown_command
movlw 0fah
call ps2transmit ; ACK
reset1
goto ps2init ; リセット
; -----------------------------------------------------------------------------
unknown_command
; 解らないコマンドがきたらどうしよう?
; とりあえず ACK でも返しとけ!
movlw 0fah
call ps2transmit ; ACK
; -----------------------------------------------------------------------------
main_keyin
btfsc PORTA,X68_READY ; キーボードから
goto main ; データを受信しなければ何もしない
bcf INTCON,GIE ; 割り込み禁止
; 割り込み処理内でテーブル処理を
; 行っているので、
; PCLATH を書き換えている間に割り込みが入ると
; まずいので、割り込み禁止にする
movlw 003h
movwf PCLATH
movlw 01111111b
andwf x68rxd,0
call table
movwf temp1
movlw 000h
movwf PCLATH
movf temp1,0
call disp_h
movf temp1,1
btfsc STATUS,Z ; テーブルから00hが帰ってきた(キー未割り当て)
goto main_keyin_end ; なら、なにもしない
btfsc temp1,7
goto exkey
; 通常キー
btfsc x68rxd,7
goto release
; 押された
movf temp1,0
call ps2transmit
goto main_keyin_end
release
; 離された
movlw 0f0h
call ps2transmit
movf temp1,0
call ps2transmit
goto main_keyin_end
exkey
; 拡張キー
btfsc x68rxd,7
goto exkey_release
; 押された
movlw 0e0h
call ps2transmit
movf temp1,0
call ps2transmit
goto main_keyin_end
exkey_release
; 離された
movlw 0e0h
call ps2transmit
movlw 0f0h
call ps2transmit
movf temp1,0
call ps2transmit
goto main_keyin_end
main_keyin_end
bsf INTCON,GIE ; 割り込み許可
goto main
; -----------------------------------------------------------------------------
; -----------------------------------------------------------------------------
; PS/2
; 受信処理
; 受信すべきデータがを見つけたら com_status,ps2rxdfound をセット
; 受信がホストに中断されると com_status,ps2break フラグを1にして戻ります
; 正常に受信すると com_status,ps2rxdvalid セットし
; ps2rxd に受信データをいれて帰ってくる
; エラー(com_status,ps2rxdvalid が 0)の場合
; com_status,ps2rxdfound が 0 なら受信すべきデータが無かった。
; 1 なら 受信動作を行ったが、パリティエラーかフレーミングエラーが発生した
ps2receive
bcf com_status,ps2rxdvalid ; データ有効フラグをクリア
bcf com_status,ps2rxdfound
bcf com_status,ps2break
movlw 11111111b
movwf PORTB
; スタートビットの取り込み
ps2receive_startbit
btfsc PORTB,PS2_DATA ; スタートビットが見つからなければ
return ; 終了
bsf com_status,ps2rxdfound
bsf com_status,ps2break
movlw 1
movwf ps2parity ;パリティ計算用変数を初期化
movlw 8
movwf ps2count ; count=8
; 8ビット分データを取り込む
ps2receive_data
call ps2clk ; クロックを出す
movlw 11111111b
movwf PORTB
rrf ps2rxd,1
btfsc PORTB,PS2_DATA ; データを取り込む
goto ps2receive_b1
ps2receive_b0
bcf ps2rxd,7
goto ps2receive_data_end
ps2receive_b1
bsf ps2rxd,7
incf ps2parity,1 ; parity+1
ps2receive_data_end
btfss PORTB,PS2_CLK ; ホストがCLKをLにしてきたら
return ; 処理中断
decfsz ps2count,1 ; count-1
goto ps2receive_data
; パリティビットの取り込み
ps2receive_parity
call ps2clk ; クロックを出す
movlw 11111111b
movwf PORTB
btfss PORTB,PS2_CLK ; ホストがCLKをLにしてきたら
return ; 処理中断
movlw 00000001b
andwf ps2parity,1 ; ps2parity のbit0のみ取り出し
btfsc PORTB,PS2_DATA
goto ps2receive_parity1
ps2receive_parity0
movf ps2parity,1
btfss STATUS,Z
goto ps2receive_perror ; パリティエラー
goto ps2receive_parity_end
ps2receive_parity1
movf ps2parity,1
btfsc STATUS,Z
goto ps2receive_perror ; パリティエラー
ps2receive_parity_end
; ストップビットの取り込み
ps2receive_stopbit
call ps2clk ; クロックを出す
movlw 11111111b
movwf PORTB
btfss PORTB,PS2_CLK ; ホストがCLKをLにしてきたら
return ; 処理中断
bcf com_status,ps2break
btfss PORTB,PS2_DATA ; ストップビットと思われるところが
goto ps2receive_end ; 0だったらエラー
; 受信終了
bsf com_status,ps2rxdvalid ; データ有効フラグをセット
call ps2clk ; クロックを出す
movlw 11111101b
movwf PORTB ; データラインをLにする
ps2receive_perror
call ps2clk ; クロックを出す
movlw 11111111b
movwf PORTB ; データラインをHにする
ps2receive_end
btfsc PORTB,PS2_DATA
goto ps2receive_return ; データラインがHなら終了処理
call ps2clk ; データラインがLならHになるまで
movlw 11111111b ; クロックを出す
movwf PORTB
goto ps2receive_end
ps2receive_return
btfsc com_status,ps2rxdvalid
return ; 正常受信なら終了
ps2receive_resend
; 受信エラーの為、再送要求
btfss PORTB,PS2_CLK ; CLKがLならHになるまで待つ
goto ps2receive_resend
btfss PORTB,PS2_DATA
goto ps2receive ; DATA がLなら再度受信処理
movlw 0feh
call ps2transmit ; Resend コマンド発行
return
;-----------------------------------------------------------------------------
; 送信処理
; wレジスタにデータを入れてコールすると
; PS/2キーボードへ向けて送信する
; 送信がホストに中断されると com_status,ps2break フラグを1にして戻ります
ps2transmit
movwf ps2txd
movwf lastdata
bsf com_status,ps2break
movlw 1
movwf ps2parity ;パリティ計算用変数を初期化
movlw 8
movwf ps2count ; count=8
movlw 11111111b
movwf PORTB
btfss PORTB,PS2_CLK ; CLKがLなら
goto ps2transmit ; Hになるまで待つ
btfss PORTB,PS2_DATA ; DATAがLなら、なにもしない
return ; 戻り先で受信処理を行って欲しい
ps2transmit_startbit
movlw 11111101b
movwf PORTB ; スタートビットをセット
; bcf PORTB,PS2_DATA ; スタートビットをセット
call ps2clk ; クロックを出す
btfss PORTB,PS2_CLK ; ホストがCLKをLにしてきたら
return ; 処理中断
ps2transmit_data
btfsc ps2txd,0 ; データをセット
goto ps2transmit_data1
ps2transmit_data0
bcf PORTB,PS2_DATA
goto ps2transmit_wait1
ps2transmit_data1
bsf PORTB,PS2_DATA
incf ps2parity,1 ; parity+1
ps2transmit_wait1
call ps2clk ; クロックを出す
btfss PORTB,PS2_CLK ; ホストがCLKをLにしてきたら
return ; 処理中断
rrf ps2txd,1 ; 右シフト
decfsz ps2count,1 ; count-1
goto ps2transmit_data
ps2transmit_parity
btfsc ps2parity,0 ; パリティをセット
goto ps2transmit_parity1
ps2transmit_parity0
bcf PORTB,PS2_DATA
goto ps2transmit_wait2
ps2transmit_parity1
bsf PORTB,PS2_DATA
ps2transmit_wait2
call ps2clk ; クロックを出す
btfss PORTB,PS2_CLK ; ホストがCLKをLにしてきたら
return ; 処理中断
ps2transmit_stopbit
bsf PORTB,PS2_DATA ; ストップビットをセット
call ps2clk ; クロックを出す
btfss PORTB,PS2_CLK ; ホストがCLKをLにしてきたら
return ; 処理中断
; 送信おしまい
ps2transmit_end
movlw 11111111b
movwf PORTB
bcf com_status,ps2break
return
ps2clk
movlw 7
call waitus
; movlw 11111110b
; movwf PORTB ; CLK をLにする
bcf PORTB,PS2_CLK
movlw 7
call waitus
; movlw 11111111b
; movwf PORTB ; CLK をHにする
bsf PORTB,PS2_CLK
return
; -----------------------------------------------------------------------------
; -----------------------------------------------------------------------------
; wレジスタの内容を16進表記で表示する
; 例
; 1: movlw 0ah ; w=0ah
; 2: call disp_h
; と実行するとLCDに
; +----------------+
; |0A_ |
; | |
; +----------------+ と表示する
disp_h
clrf lcd_temp4 ; lcd_temp5=0
movwf lcd_temp3 ; lcd_temp3=w
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
; -----------------------------------------------------------------------------
; -----------------------------------------------------------------------------
; wレジスタの値に応じて 10マイクロ秒 単位のウェイトを入れる
; 使用変数
; wait_count1,wait_count2
; 例、約20μs待つ
; 1: movlw 2
; 2: call waitus
; メモ
; 使用クロックに応じて、定数 CONST_WAIT_US を定義してください
; CONST_WAIT_US = 10/(1/動作クロック[MHz]*4*3)
; 例、8Mhz時
; CONST_WAIT_US equ 7
waitus
movwf wait_count1 ; wait_count1=w
waitus_loop1
movlw CONST_WAIT_US
movwf wait_count2 ; wait_count2=CONST_WAIT_US
waitus_loop2
decfsz wait_count2,1 ; wait_count2=wait_count2-1
goto waitus_loop2 ; if wait_count2!=0 goto waitus_loop2
decfsz wait_count1,1 ; wait_count1=wait_count1-1
goto waitus_loop1 ; if wait_count1!=0 goto waitus_loop1
return ; else return
; -----------------------------------------------------------------------------
; -----------------------------------------------------------------------------
; キーコード変換テーブル
; PS2のキーコードが複数バイトあって、どう処理しようか困った
; とりあえず、拡張キーは bit7 を 1 にしてみる方針でやってみる
; キーの割り当てを変えたい場合は、このテーブルを書き換えてね
org 300h
table
addwf PCL,1
retlw 000h ; 00h
retlw 076h ; 01h [ESC]
retlw 016h ; 02h [1]
retlw 01Eh ; 03h [2]
retlw 026h ; 04h [3]
retlw 025h ; 05h [4]
retlw 02Eh ; 06h [5]
retlw 036h ; 07h [6]
retlw 03Dh ; 08h [7]
retlw 03Eh ; 09h [8]
retlw 046h ; 0Ah [9]
retlw 045h ; 0Bh [0]
retlw 04Eh ; 0Ch [-]
retlw 055h ; 0Dh [^]
retlw 06Ah ; 0Eh [\]
retlw 066h ; 0Fh [BS]
retlw 00Dh ; 10h [TAB]
retlw 015h ; 11h [Q]
retlw 01Dh ; 12h [W]
retlw 024h ; 13h [E]
retlw 02Dh ; 14h [R]
retlw 02Ch ; 15h [T]
retlw 035h ; 16h [Y]
retlw 03Ch ; 17h [U]
retlw 043h ; 18h [I]
retlw 044h ; 19h [O]
retlw 04Dh ; 1Ah [P]
retlw 054h ; 1Bh [@]
retlw 05Bh ; 1Ch [[]
retlw 05Ah ; 1Dh [RETURN]
retlw 01Ch ; 1Eh [A]
retlw 01Bh ; 1Fh [S]
retlw 023h ; 20h [D]
retlw 02Bh ; 21h [F]
retlw 034h ; 22h [G]
retlw 033h ; 23h [H]
retlw 03Bh ; 24h [J]
retlw 042h ; 25h [K]
retlw 04Bh ; 26h [L]
retlw 04Ch ; 27h [;]
retlw 052h ; 28h [:]
retlw 05Dh ; 29h []]
retlw 01Ah ; 2Ah [Z]
retlw 022h ; 2Bh [X]
retlw 021h ; 2Ch [C]
retlw 02Ah ; 2Dh [V]
retlw 032h ; 2Eh [B]
retlw 031h ; 2Fh [N]
retlw 03Ah ; 30h [M]
retlw 041h ; 31h [,]
retlw 049h ; 32h [.]
retlw 04Ah ; 33h [/]
retlw 051h ; 34h [ろ]
retlw 029h ; 35h [SPACE]
retlw 0ECh ; 36h [HOME]
retlw 0F1h ; 37h [DEL]
retlw 0FDh ; 38h [ROLL UP]
retlw 0FAh ; 39h [ROLL DOWN]
retlw 0E9h ; 3Ah [UNDO] - [END]
retlw 0EBh ; 3Bh [←]
retlw 0F5h ; 3Ch [↑]
retlw 0F4h ; 3Dh [→]
retlw 0F2h ; 3Eh [↓]
retlw 077h ; 3Fh [CLR] - [NUM LOCK]
retlw 0CAh ; 40h [/] (10key)
retlw 07Ch ; 41h [*] (10key)
retlw 07Bh ; 42h [-] (10key)
retlw 06Ch ; 43h [7] (10key)
retlw 075h ; 44h [8] (10key)
retlw 07Dh ; 45h [9] (10key)
retlw 079h ; 46h [+] (10key)
retlw 06Bh ; 47h [4] (10key)
retlw 073h ; 48h [5] (10key)
retlw 074h ; 49h [6] (10key)
retlw 055h ; 4Ah [=] (10key)
retlw 069h ; 4Bh [1] (10key)
retlw 072h ; 4Ch [2] (10key)
retlw 07Ah ; 4Dh [3] (10key)
retlw 0DAh ; 4Eh [ENTER] (10key)
retlw 070h ; 4Fh [0] (10key)
retlw 049h ; 50h [,] (10key)
retlw 071h ; 51h [.] (10key)
retlw 000h ; 52h [記号入力]
retlw 000h ; 53h [登録]
retlw 000h ; 54h [HELP]
retlw 000h ; 55h [XF1]
retlw 000h ; 56h [XF2]
retlw 000h ; 57h [XF3]
retlw 000h ; 58h [XF4]
retlw 000h ; 59h [XF5]
retlw 078h ; 5Ah [かな] - [F11]
retlw 007h ; 5Bh [ローマ字] - [F12]
retlw 000h ; 5Ch [カナ入力]
retlw 058h ; 5Dh [CAPS]
retlw 0F0h ; 5Eh [INS]
retlw 000h ; 5Fh [ひらがな]
retlw 000h ; 60h [全角]
retlw 000h ; 61h [BREAK]
retlw 000h ; 62h [COPY]
retlw 005h ; 63h [F1]
retlw 006h ; 64h [F2]
retlw 004h ; 65h [F3]
retlw 00Ch ; 66h [F4]
retlw 003h ; 67h [F5]
retlw 00Bh ; 68h [F6]
retlw 083h ; 69h [F7]
retlw 00Ah ; 6Ah [F8]
retlw 001h ; 6Bh [F9]
retlw 009h ; 6Ch [F10]
retlw 000h ; 6Dh
retlw 000h ; 6Eh
retlw 000h ; 6Fh
retlw 012h ; 70h [SHIFT]
retlw 014h ; 71h [CTRL]
retlw 000h ; 72h [OPT.1]
retlw 000h ; 73h [OPT.2]
retlw 000h ; 74h
retlw 000h ; 75h
retlw 000h ; 76h
retlw 000h ; 77h
retlw 000h ; 78h
retlw 000h ; 79h
retlw 000h ; 7Ah
retlw 000h ; 7Bh
retlw 000h ; 7Ch
retlw 000h ; 7Dh
retlw 000h ; 7Eh
retlw 000h ; 7Fh
('A`)