; ; X68000のキーボードを ; AT互換機のPS/2ポートにつなぐのです ; キー入力に関してはほぼ完成版。ホストコマンドをたびたび取りこぼす ; 2001/11/28 作成 ; 2001/11/30 一応完成 ; ; 秋月アセンブラ(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 X68_RxD equ 0 ; RA0 - X68 KY RxD X68_TxD equ 1 ; RA1 - X68 KY TxD X68_READY equ 2 ; RA2 - X68 KY READY ; RA3 - 未使用 ; RA4 - 未使用 ; PORT B PS2_CLKOUT equ 0 ; RB0 - PS/2 CLK PS2_CLKIN equ 1 ; RB1 - PS/2 CLK PS2_DATAOUT equ 2 ; RB2 - PS/2 DATA PS2_DATAIN equ 3 ; RB3 - PS/2 DATA ; ; RB4 - 未使用 ; ; RB5 - 未使用 ; ; RB6 - 未使用 ; ; RB7 - 未使用 ; ---------------------------------------------------------------------------- ; ; 回路図 ; ; PS/2コネクタ ; ; +5V -----------+---- +5V ; | ; = C1 ; |- ; GND -----------+---- GND ; ; ; +--------+ ; | Vdd|----+-- +5V ; | | | ; |PIC16C84| = C2 ; | | | ; | Vss|----+-- GND ; | | ; | | C3 ; | OSC1|----+--||-- GND ; | | | ; | | = X'tal1 ; | | | ; | OSC2|----+--||-- GND ; | | C3 ; | | ; | /MCLR|---R4-- +5V ; +--------+ ; ; ; ; ; +5V ; | ; R1 ; | ; RB1 CLKIN --R2-+---- PS/2 CLK ; | ; RB0 CLKOUT --R3-K TR1 ; | ; GND ; ; +5V ; | ; R1 ; | ; RB3 DATAIN --R2-+---- PS/2 CLK ; | ; RB2 DATAOUT --R3-K TR1 ; | ; GND ; R1 4.7k ; R2 330 ; R3 12k ; R4 1k ; C1 47u ; C2 0.1u ; C3 22p ; TR1 2SC1815 ; ; ; X68キーボードコネクタ ; ; +5V -------------- VCC2 1pin ; GND -------------- GND 7pin ; ; RA0 RxD -------------- TxD 3pin ; ; RA1 TxD -------------- RxD 4pin ; ; RA2 READY -------------- T0 5pin ; ; ---------------------------------------------------------------------------- .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 200 ; ms 単位のウェイト用定数 ; CONST_WAIT_MS = (動作クロック[MHz]/4)*100 CONST_WAIT_US equ 6 ; 10μs 単位のウェイト用定数 ; CONST_WAIT_US = 10/(1/動作クロック[MHz]*4*3) CONST_COMSPEED equ 155 ; シリアル通信用割り込み間隔 ; CONST_COMSPEED = 255-(動作クロック[Hz]/bps/32)+4(くらい) ; ----------------------------------------------------------------------------- ; 変数を宣言 org 0ch keycode ds 1 ; キーコードの一時保存 prtsc ds 1 ; Print Screen キーのリピート処理用カウンタ status_led ds 1 ; ステータスLED状態保持 SCRLK equ 1 NUMLK equ 2 CAPSLK equ 3 lastdata ds 1 ; PS/2ポートに前回送出したデータ 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 PORTA,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 PORTA,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 PORTA,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 PORTA,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 PORTA,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 PORTA,X68_TxD ;送信バッファのbit0が0なら0を送信 goto intx68tmode1_8end intx68tmode1_8_1 bsf PORTA,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 PORTA,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 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 11100001b ; ||||+----- X68 KY RxD in ; |||+------ X68 KY TxD out ; ||+------- X68_READY out ; |+-------- RA3 - 未使用 in ; +--------- RA4 - 未使用 in movwf TRISA ; 設定レジスタに書き込み ; ポートB movlw 00001010b ; |||||||+----- PS/2 CLKOUT out ; ||||||+------ PS/2 CLKIN in ; |||||+------- PS/2 DATAOUT out ; ||||+-------- PS/2 DATAIN in ; |||+--------- RB4 - 未使用 out ; ||+---------- RB5 - 未使用 out ; |+----------- RB6 - 未使用 out ; +------------ RB7 - 未使用 out movwf TRISB ; 設定レジスタに書き込み bcf STATUS,RP0 ; bank0 ; 通信ポートの初期化 bcf PORTA,X68_READY ; bsf PORTA,X68_RxD bsf PORTA,X68_TxD bcf PORTB,PS2_CLKOUT ; bsf PORTB,PS2_CLKIN bcf PORTB,PS2_DATAOUT ; bsf PORTB,PS2_DATAIN ; 変数の初期化 clrf int_x68rmode clrf int_x68rcount clrf int_x68tcount clrf int_x68tmode clrf com_status ; 割り込み許可 movlw 10100000b movwf INTCON ; TMR0割り込み許可 ; ----------------------------------------------------------------------------- ; ----------------------------------------------------------------------------- ; PS/2 キーボードとしての初期化処理 ps2init movlw 255 call wait ps2init1 btfsc com_status,x68transmitrq ; キーボードへ送信処理中なら goto ps2init1 ; 終わるまで待つ movlw 10000000b movwf x68txd bsf com_status,x68transmitrq ; LED全点灯 movlw 250 call wait movlw 250 call wait btfss PORTB,PS2_DATAIN goto main ; DATA がLなら受信処理 movlw 0aah call ps2transmit ; セルフテストOK送信 ; btfsc com_status,ps2break ; goto ps2init ; 送信が中断されたらもう一回 ps2init5 btfsc com_status,x68transmitrq ; キーボードへ送信処理中なら goto ps2init5 ; 終わるまで待つ movlw 11111111b movwf x68txd bsf com_status,x68transmitrq ; LED全消灯 ; ----------------------------------------------------------------------------- ; ----------------------------------------------------------------------------- main ; X68キーボードデータ送出許可 bsf PORTA,X68_READY ; ホストコマンドの処理 hostcommand call ps2receive btfss com_status,ps2rxdvalid goto main_keyin ; 受信しなければキー入力処理 movlw 100 call waitus ; 重要 ; ----------------------------------------------------------------------------- set_status_led movlw 0edh subwf ps2rxd,0 btfss STATUS,Z goto echo movlw 0fah call ps2transmit ; ACK movlw 100 call waitus 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 50 call waitus 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 movlw 100 call waitus set_scancode1 call ps2receive btfss com_status,ps2rxdvalid goto set_scancode1 movlw 100 call waitus 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 movlw 100 call waitus set_repeatrate1 call ps2receive btfss com_status,ps2rxdvalid goto set_repeatrate1 ;*************************************** movlw 100 call waitus 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 0feh subwf ps2rxd,0 btfss STATUS,Z goto reset resend1 movf lastdata,0 call ps2transmit ; resend goto main_keyin ; ----------------------------------------------------------------------------- reset movlw 0ffh 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 ; データを受信しなければ何もしない main_keyin1 btfsc com_status,x68transmitrq ; キーボードへ送信処理中なら goto main_keyin1 ; 終わるまで待つ bcf INTCON,GIE ; 割り込み禁止 ; 割り込み処理内でテーブル処理を ; 行っているので、 ; PCLATH を書き換えている間に割り込みが入ると ; まずいので、割り込み禁止にする movlw 003h movwf PCLATH movlw 01111111b andwf x68rxd,0 call table movwf keycode ; ----------------------------------------------------------------------------- movlw 000h movwf PCLATH movf keycode,1 btfsc STATUS,Z ; テーブルから00hが帰ってきた(キー未割り当て) goto main_keyin_end ; なら、なにもしない ; ----------------------------------------------------------------------------- ; [Print Screen] キーの処理 printscreen movlw 0feh subwf keycode,0 btfss STATUS,Z goto pause btfsc x68rxd,7 goto printscreen_release ; 押された printscreen_press movf prtsc,1 btfsc STATUS,Z ; 1回目のみ E0 12 E0 7C を送信 goto printscreen_press2 ; 2回目から E0 7C を送信 decf prtsc,1 movlw 0e0h call ps2transmit movlw 50 call waitus movlw 012h call ps2transmit movlw 50 call waitus printscreen_press2 movlw 0e0h call ps2transmit movlw 50 call waitus movlw 07ch call ps2transmit goto main_keyin_end ; 離された printscreen_release movlw 0e0h call ps2transmit movlw 50 call waitus movlw 0f0h call ps2transmit movlw 50 call waitus movlw 07ch call ps2transmit movlw 50 call waitus movlw 0e0h call ps2transmit movlw 50 call waitus movlw 0f0h call ps2transmit movlw 50 call waitus movlw 012h call ps2transmit goto main_keyin_end ; ----------------------------------------------------------------------------- ; [Pause] キーの処理 pause movlw 0ffh subwf keycode,0 btfss STATUS,Z goto main_keyin2 btfsc x68rxd,7 goto pause_release ; 押された pause_press movlw 0e1h call ps2transmit movlw 50 call waitus movlw 014h call ps2transmit movlw 50 call waitus movlw 077h call ps2transmit movlw 50 call waitus movlw 0e1h call ps2transmit movlw 50 call waitus movlw 0f0h call ps2transmit movlw 50 call waitus movlw 014h call ps2transmit movlw 50 call waitus movlw 0f0h call ps2transmit movlw 50 call waitus movlw 077h call ps2transmit goto main_keyin_end ; 離された pause_release ; なにもしない goto main_keyin_end ; ----------------------------------------------------------------------------- ; そのほか普通のキーの処理 main_keyin2 btfsc keycode,7 ; 通常キーか拡張キーかを bit7 で判断 goto exkey ; 通常キー normaliy btfsc x68rxd,7 goto release ; 押された press movf keycode,0 call ps2transmit goto main_keyin_end ; 離された release movlw 0f0h call ps2transmit movlw 50 call waitus movf keycode,0 call ps2transmit goto main_keyin_end ; ----------------------------------------------------------------------------- ; 拡張キー exkey movlw 01111111b andwf keycode,1 btfsc x68rxd,7 goto exkey_release ; 押された movlw 0e0h call ps2transmit movlw 50 call waitus movf keycode,0 call ps2transmit goto main_keyin_end ; 離された exkey_release movlw 0e0h call ps2transmit movlw 50 call waitus movlw 0f0h call ps2transmit movlw 50 call waitus movf keycode,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 ; スタートビットの取り込み ps2receive_startbit btfsc PORTB,PS2_DATAIN ; スタートビットが見つからなければ return ; 終了 bsf com_status,ps2rxdfound bsf com_status,ps2break movlw 1 movwf ps2parity ;パリティ計算用変数を初期化 movlw 8 movwf ps2count ; count=8 ; 8ビット分データを取り込む ps2receive_data call ps2clkr ; クロックを出す rrf ps2rxd,1 btfsc PORTB,PS2_DATAIN ; データを取り込む 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_CLKIN ; ホストがCLKをLにしてきたら return ; 処理中断 decfsz ps2count,1 ; count-1 goto ps2receive_data ; パリティビットの取り込み ps2receive_parity call ps2clkr ; クロックを出す btfss PORTB,PS2_CLKIN ; ホストがCLKをLにしてきたら return ; 処理中断 movlw 00000001b andwf ps2parity,1 ; ps2parity のbit0のみ取り出し btfsc PORTB,PS2_DATAIN 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 ps2clkr ; クロックを出す bcf com_status,ps2break btfss PORTB,PS2_DATAIN ; ストップビットと思われるところが goto ps2receive_end ; 0だったらエラー ; 受信終了 bsf com_status,ps2rxdvalid ; データ有効フラグをセット bsf PORTB,PS2_DATAOUT ; データラインをLにする call ps2clkr ; クロックを出す ps2receive_perror bcf PORTB,PS2_DATAOUT ; データラインをHにする call ps2clkr ; クロックを出す ps2receive_end btfsc PORTB,PS2_DATAIN goto ps2receive_return ; データラインがHなら終了処理 call ps2clkr ; データラインがLならHになるまで goto ps2receive_end ; クロックを出す ps2receive_return btfsc com_status,ps2rxdvalid return ; 正常受信なら終了 ps2receive_resend ; 受信エラーの為、再送要求 btfss PORTB,PS2_CLKIN ; CLKがLならHになるまで待つ goto ps2receive_resend ps2receive_resend1 movlw 50 call waitus btfss PORTB,PS2_DATAIN goto ps2receive ; DATA がLなら再度受信処理 movlw 0feh call ps2transmit ; Resend コマンド発行 btfsc com_status,ps2break goto ps2receive_resend1 ; 送信が中断されたらもう一回 movlw 50 call waitus 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 btfss PORTB,PS2_CLKIN ; CLKがLなら goto ps2transmit ; Hになるまで待つ btfss PORTB,PS2_DATAIN ; DATAがLなら、なにもしない return ; 戻り先で受信処理を行って欲しい ps2transmit_startbit bsf PORTB,PS2_DATAOUT ; スタートビットをセット call ps2clk ; クロックを出す btfss PORTB,PS2_CLKIN ; ホストがCLKをLにしてきたら goto ps2transmit_break ; 処理中断 ps2transmit_data btfsc ps2txd,0 ; データをセット goto ps2transmit_data1 ps2transmit_data0 bsf PORTB,PS2_DATAOUT goto ps2transmit_wait1 ps2transmit_data1 bcf PORTB,PS2_DATAOUT incf ps2parity,1 ; parity+1 ps2transmit_wait1 call ps2clk ; クロックを出す btfss PORTB,PS2_CLKIN ; ホストがCLKをLにしてきたら goto ps2transmit_break ; 処理中断 rrf ps2txd,1 ; 右シフト decfsz ps2count,1 ; count-1 goto ps2transmit_data ps2transmit_parity btfsc ps2parity,0 ; パリティをセット goto ps2transmit_parity1 ps2transmit_parity0 bsf PORTB,PS2_DATAOUT goto ps2transmit_wait2 ps2transmit_parity1 bcf PORTB,PS2_DATAOUT ps2transmit_wait2 call ps2clk ; クロックを出す btfss PORTB,PS2_CLKIN ; ホストがCLKをLにしてきたら goto ps2transmit_break ; 処理中断 ps2transmit_stopbit bcf PORTB,PS2_DATAOUT ; ストップビットをセット call ps2clk ; クロックを出す ; 送信おしまい ps2transmit_end bcf com_status,ps2break ps2transmit_break bcf PORTB,PS2_DATAOUT return ps2clk movlw 2 call waitus bsf PORTB,PS2_CLKOUT movlw 1 call waitus bcf PORTB,PS2_CLKOUT movlw 1 call waitus return ps2clkr movlw 2 call waitus bsf PORTB,PS2_CLKOUT movlw 1 call waitus bcf PORTB,PS2_CLKOUT movlw 1 call waitus 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 ; ----------------------------------------------------------------------------- ; ----------------------------------------------------------------------------- ; キーコード変換テーブル ; キーの割り当てを変えたい場合は、このテーブルを書き換えてね 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 0FAh ; 38h [ROLL UP] - [Page Doun] retlw 0FDh ; 39h [ROLL DOWN] - [Page Up] 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 04Eh ; 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 041h ; 50h [,] (10key) retlw 071h ; 51h [.] (10key) retlw 067h ; 52h [記号入力] - [無変換] retlw 07Eh ; 53h [登録] - [ScroolLocK] retlw 000h ; 54h [HELP] retlw 09Fh ; 55h [XF1] - [ミ田] retlw 011h ; 56h [XF2] - [Alt] retlw 064h ; 57h [XF3] - [変換] retlw 091h ; 58h [XF4] - [Alt] retlw 0AFh ; 59h [XF5] - [(メニュー)] retlw 078h ; 5Ah [かな] - [F11] retlw 007h ; 5Bh [ローマ字] - [F12] retlw 000h ; 5Ch [コード入力] retlw 058h ; 5Dh [CAPS] retlw 0F0h ; 5Eh [INS] retlw 013h ; 5Fh [ひらがな] retlw 00Eh ; 60h [全角] retlw 0FFh ; 61h [BREAK] - [Pause] retlw 0FEh ; 62h [COPY] - [PrintScreen] 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 059h ; 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