まごころせいじつ堂

浜町庄金 研究開発  マイコンで遊んでばっかりで

PS2

マイコンとPS/2キーボードを繋ぐあれこれ

PS/2やADB(Appleの古いキーボードI/F)をUSBに変換する。AVR用。
https://github.com/tmk/tmk_keyboard 

Adafruitの新製品。
NEW PRODUCT! E1115 PS/2 Keyboard to TTL Serial Converter 

うう、色々先を越された。

PS/2キーボード変換器の製作(15) US配列→JP配列の問題点

US配列から日本語配列に変換する部分を作成した。
Arduino用のスケッチは以下のとおり。これはUSB HIDキーボードに文字を出力すると共にシリアルポートにデバッグ情報を流す。
https://gist.github.com/3464019
ライブラリ(ps2kybd.h、ps2kybd.cpp)は前回から修正なし。
https://gist.github.com/ab100bfb33a78ddf067d



記号の置き換えは、以下のパターンで行う。
(1)SHIFTを押していない状態でSHIFTを押したような入力……右シフトキーpress、置き換えコード、右シフトキーrelease
(2)SHIFTを押していない状態で記号の置き換え……置き換えコード
(3)SHIFTを押した状態でSHIFTを押したような入力……置き換えコード
(4)SHIFTを押した状態でSHIFTを押さないような入力……左右のシフトキーをrelease、置き換えコード、元のシフトキーをpress

ALTキーを押した状態では、[`~]キーは変換せずにそのまま出力することで[ALT]+[漢字]と同じ操作になる。

 これで記号の置き換え、漢字入力のON/OFFができた。

 残った問題点。
(1)CapsLockの扱い。CapsLockはUSキーではSHIFT併用だが、日本語キーではそのまま。
→Capsフラグはライブラリ側にまかせているが、これをスケッチ側で対処
(2)[¥_]が入力できない →Arduino LeonardoはいったんASCIIコードで受けて内部で変換しUSB HIDコードを送っている。USキーのレイアウトを前提にしているため、日本語配列の[¥_]は対応するものがない。
(3)このアダプタをWindowsXPに接続するたびにデバイスドライバの確認ダイアログが登場する。

(2)、(3)は非常に大きな問題。

(2)はUSB HIDを直接送出する方法を調べなければならない。
(3)はArduinoのブートローダを置き換えなければならない。

うーん、これはけっこう難しいぞ……

POS端末用PS/2キーボード FTP-CKB11の解析

 昔ジャンク屋で入手したPOS用のPS/2接続キーボード。テンキー以外はラベルを入れることができる。鍵付き。
2011pos01

 裏面はツメで嵌めこまれているだけなので簡単に外れる。キーボードのくせに基板が複雑。16bitマイコンが載っていた。
F2MC-16L MB90610A Series[pdf]

2012pos02

 これは磁気カードリーダーにも対応しているためだろう。フラッシュメモリも搭載されていたのでログを取るのかもしれない。

2012pos03

解析結果

pos_scancode
 

富士通コンポーネントKB8811-251のスキャンコード

 また脱線。

 富士通コンポーネント(元 富士通高見澤)製のFKB8811-251。赤外線ワイヤレスのPS/2キーボード。10年くらい前に入手。赤外線受信機はマウス出力もある。赤外線を出すマウスもあったのだろうけど、私が買ったものにはついてなかった。

2012kybd251_1

 赤外線受信機側にCapsLock等のLEDがあるので、キーボード本体はキーに対応したコードを送るだけと思われる。

2012kybd251_2


 FKB8811で検索するとラック用のコンパクトキーボードとして出てくる。これをワイヤレスにしてマルチメディア関連のキーを追加したものらしい。この追加されたキーのスキャンコードが気になって調べた。

停止(■)	E0 3B / E0 F0 3B	なし
再生・一時停止(▶||)	E0 34 / E0 F0 34	なし
巻き戻し(|<<)	E0 15 / E0 F0 15	あり
早送り(>>|)	E0 4D / E0 F0 4D	あり
Vol-	E0 21 / E0 F0 21	あり
Mute	E0 23 / E0 F0 23	なし
Vol+	E0 32 / W0 F0 32	あり
App1	56 / F0 56	なし
App2	5E / F0 5E	なし
App3	8 / F0 8	なし
Email	18 / E0 18	なし
Internet	10 / E0 10	なし
ScreenSaver	65 / E0 65	なし
Sleep	E0 3F / E0 F0 3F	なし

PS/2キーボードの Power,Sleep,Wakeキー

またもや脱線。

 ELECOM TK-FCM008BK、これ112キーとあり、普通のPS/2キーボードにはないPower、Sleep、Wakeキーが付いている。500円台だったので買って調べてみた。

2012ps2

スキャンコード
キー名称 make / release
Power	E0 37 / E0 F0 37
Sleep	E0 3F / E0 F0 3F
Wake	E0 5E / E0 F0 5E
Powerキーは押すと電源OFFすることができる。ONはできない。PC本体が電源OFFの時にはPS/2キーボードに給電されていないからだ。しかしPowerキーの位置、危険な香り。

ELECOM メンブレン式キーボード 112キー PS2 スタンダードサイズ ブラック TK-FCM008BKELECOM メンブレン式キーボード 112キー PS2 スタンダードサイズ ブラック TK-FCM008BK

エレコム 2009-08-21
売り上げランキング : 3869

Amazonで詳しく見る
by G-Tools

記事タイトルPS/2キーボード変換器の製作(14) US配列でPS/2→USB変換OK

PS/2のスキャンコードをUSB UserIDまで変換できた。次にArduino Leonardoで扱っているコードに変換する。変換方法はほぼ同じで、テーブルを別に用意する。

https://gist.github.com/ab100bfb33a78ddf067d

PrtScr / ScrLock / Break まわりが難航した。ここはスキャンコードが面倒。
USBのコードをKeyboard.press()やKeyboard.release()で操作する時には充分に注意しないとスケッチの修正ができなくなる。Arduino IDEからソースをコンパイルする時にスケッチ画面に文字がタイプされてしまうからだ。

・Windows7(64bit)(英語キーボード配列の設定)に本アダプタと英語キーボードを接続し確認
・WindowsXP(日本語キーボード配列の設定)に本アダプタと日本語キーボードを接続し確認

○(1)PrintScreen / ALT+PrintScreen 正常動作
○(2)ScrLock正常動作(Excelで確認)
○(3)[目](App)キー正常動作
○(4)日本語入力/英数入力切り換え確認OK
○(5)接続したままPC本体電源ONでも動作OK。Windows7のパスワード入力も確認
×(6)[\ろ] キーと[¥]キーを\に対応させたいのだがうまくいかない(日本語キーボード接続時)
→これは無視してもよいか?

Arduino Leonardoのライブラリの制限で、PC側の[無変換][変換][かな]キーに対応するコードを送ることができない。外付けキーボードの[無変換][変換][かな]キーを別のキーに割り当てることは可能。

その他の問題点:
(a)アダプタを接続するたびにデバイスマネージャがデバイスドライバを探す。(WindowsXP)
Windows7ではドライバがインストールできなかったことを通知。でも気持ち悪い。
→できればArduino用のドライバを入れずに動かしたい

(b)キーボードのステータスがわからない。
→PC本体からの指示を受け取る手段がない。PS/2キーボード側に送信するプログラムを書いていない。
※本体接続のキーボードのランプは点灯する。

しばらく英語キーボード配列のPCに接続して使ってみる。並行してUS→JP変換のテーブルを作成。

追記:
(6)は日本語キーボードのみの問題で、キーに対応するコードがArduino Leonardoから送れないため。
(a)はブートローダ差し替えでできそう。32U4はHWB端子を見てブートローダを起動するかどうかを判断するが、Arduinoのブートローダは関連するフューズビットを設定していないらしい。 

PS/2キーボード変換器の製作(13) ハードウェアはできたが……

ハードウェアはできた。Daviciマイコンボードに6Pのmini-DINコネクタを接続、CLKとDATAをプルアップしてケース収納。
2012key01
2012key02
2012key03

 あとはPS/2のスキャンコードをUSB-UIDに変換(済)、Arduino Leonardoのkeyboard.press()に変換、さらに日本語キーボードの配列に変換するだけなのだが、問題点発覚。

以前調査した、Arduino IDE1.0.1でのコード変換部分。
Arduino IDE1.0.1/Leonardで足らないUSBキーを追加する
[HID.cpp]
	uint8_t i;
	if (k >= 136) {			// it's a non-printing key (not a modifier)
		k = k - 136;
	} else if (k >= 128) {	// it's a modifier key
		_keyReport.modifiers |= (1<<(k-128));
		k = 0;
	} else {				// it's a printing key
		k = pgm_read_byte(_asciimap + k);
		if (!k) {
			setWriteError();
			return 0;
		}
		if (k & 0x80) {						// it's a capital letter or other character reached with shift
			_keyReport.modifiers |= 0x02;	// the left shift modifier
			k &= 0x7F;
		}
	}
 上記ソースはkeybord.press()でコードを変換している箇所。与えられた数値が0x00〜0x7fを印字可能なキー、0x80〜0x87をモディファイアキー、0x88〜を表示不能な特殊キーとみなしている。0x00〜0x7fは const uint8_t _asciimap[128] で定義されてあるテーブルで変換される。0x88以上は、その値から0x88を引いた数値がUsageIDとしてUSB経由で送信される。つまり、ファンクションキーF7は #define KEY_F7 0xC8 と定義されているが、実際は0xC8ー0x88=0x40が送信される。
 ここで漏れてしまうキーは、UIDが0x78より大きいもので、日本語キーボード関連で影響がありそうなものは
[ろ](0x87)、[かたかな/ひらがな](0x88)、[¥](0x89)、[変換](0x8a)、[無変換](0x8b)、[かたかな](0x92)、[ひらがな](0x93)、[全角/半角](0x94)。
特に最後の[全角/半角](0x94)は日本語キーボードと認識している場合どうしたものか。USB-HIDをそのまま送出する方法を探すしかないのか。

 ターゲットとなるPCがキーボードを日本語配列と認識している場合、ALT+[`]が[全角/半角]と同等か調査し、もし違っていればUSB-UIDを直接送出する方法を探す。

追記: 
    Keyboard.press(KEY_LEFT_ALT);
    Keyboard.press('`');
    delay(10);
    Keyboard.release('`');
    Keyboard.release(KEY_LEFT_ALT);
 
WindowsXPにてこれで日本語入力が切り替わることを確認。助かった。MacOSXではそのままALT+`扱い。 

PS/2テンキーボード FMV-NTKB1の調査

ちょっと脱線。昔、USBポートのなかった頃のノートPCのオプションでPS/2接続のテンキーボードがあったのだが、この挙動が謎だった。スキャンコードを観測できるようになって、コードの割り当てがまったく違うことがわかった。

2012tenkey

富士通 FMV-NTKB1 テンキーボード

キー名称 make/releaseコード

NumLock 01 / 81
7home 02 / 82
4← 03 / 83
1End 04 / 84
/ 06 / 86
8↑ 07 / 87
5 08 / 88
2↓ 09 / 89
0Ins 0A / 8A
* 0B / 8B
9PgUp 0C / 8C
6→ 0D / 8D
3PgDn 0E / 8E
.Del 0F / 8F
- 10 / 90
+ 11 / 91
Enter 13 / 93

キーリピートなし

 要は専用のオプションだったってことですね。

PS/2キーボード変換器の製作(12) Scancode→USB UID変換

作業メモ:
https://gist.github.com/3056964
 

 scancodeからUSB-UserIDへの変換ができた。256バイトのテーブルを使って通常と拡張モード(0xE0)付きのスキャンコードを変換。可変長で扱いが面倒なスキャンコードをUSB-UserIDの固定長にした。
USB-UserIDは0x70に続く2バイトで表現。先頭のbit15はキーを離した時に1、とした。
 また、CTRL,SHIFT,ALT,GUI(META)キーの状態取得、Caps/Num/Scrのロック状態を取得。

 残りは特殊なキー[PrtScn]と[Pause/break]の取り扱い。特に[PrtScn]はalt併用状態をどう扱うか。
ここまでやれば英語キーボードの変換は一応済となる。

 あとはUSB-UserIDから日本語キーボード配列向けのUSB-UserIDに変換するテーブルを作成、ケース組み込み。

PS/2キーボード 特殊なキーのスキャンコード

 スキャンコードが安定して取得できるようになったので、特殊なキーについて確認した。

拡張:E0 リリース:F0

[PrtScn]
E0 12 E0 7C / E0 F0 7C E0 F0 12

[Alt]+[PrtScn]
84 / F0 84

[PrtScn]とその他[Ctrl]、[Shift]、[Meta(Windows)]を組み合わせても[Alt]優先。

※Windowsでのハードコピーが[PrtScn]と[Alt]+[PrtScn]なのはこの組み合わせしか区別がないから

[Pause/Break]
E1 14 77 E1 F0 14 F0 77

[Ctrl]+[Pause/Break]
E0 7E E0 F0 7E

[Pause/Break]を押すとすべてのキーリピートが止まる。

[App](windowsキーと一緒に追加されたマウスの右クリック相当のやつ)
E0 2F / E0 F0 2F


調査はMicrosoft Keyboard Elite(US版)でやったのでリファレンス的には問題ないだろう。

PS/2キーボード変換器の製作(11) スキャンコード取得

ArduinoでPS/2キーボードのスキャンコード取得が安定してできるようになった。ライブラリはarduino.ccのplaygroundで公開されているps2keyboardExt2を基本にps2keyboardの割り込み部分を混ぜた。ps2keyboardの方は外部割り込みでスキャンコードを受け取ったあとFIFOに入れている。(ここを自前で作ったら取り出し時に重複してしまった)

作りかけのライブラリとテスト用のスケッチ

Arduino UNOとLeonardoで挙動が違う部分に引っかかったので注意。
Arduino Leonardoの外部割り込み番号とピンの割り当てが異なる 

PS/2キーボード変換器の製作(10) 整理

・PS/2キーボード→USB接続、US配列を日本語配列に変換する。工程整理。

■開発環境とマイコンは確定
・ArduinoIDE1.0.1とArduino Leonardo(互換品)で作成。オープンソース。再現性高い。
・送り返して書きなおしたりしなくても、先方でアップデート可能

☆印は優先、これらが出来れば最低限動作

□ハードウェア
□マイコン選定(AVR ATmega32U4搭載 Arduino Leonard互換ボード、複数の選択肢があることは重要)
 ※sparkfun ATmega32U4モジュール 今回は使わない http://www.switch-science.com/products/detail.php?product_id=982
☆PS/2ポートのPullUp抵抗無くせるか 設定確認
□ケース組み込み

□ソフトウェア
■構造
 ■PS/2キーボード入出力はArduinoのライブラリとして構成 → arduino.cc playgroundのps2keyboard/ps2keyboardext2を参考
 ■USB HIDキーボード出力はArduinoIDE1.0.1の機能を利用
 ■スキャンコード→USBのコードへの変換はスケッチで行う

・ライブラリ
□PS/2キーボード入力
 ■PS/2キーボードのスキャンコード Type2決め打ちでOK(Type1は古い機種、Type3は特殊で使われない)
 ☆スキャンコードを直接扱うrawread()を追加→作成済、未確認
 ☆スキャンコードをFIFOに入れる→キー取りこぼし対策
 ☆PrintScreen/Alt+PrintScreen
 □Pause(ただしPrintScreenができればたいしたことはない)
 □NumLock時挙動 キーパッド部分
□PS/2キーボード出力
 □コマンド送出 キーボード本体のLED制御
 □コマンド送出 キーボードリピート設定

・スケッチ
☆スキャンコード PS/2-US→USB-HID変換
□スキャンコード マルチメディア系の追加キー
☆make/release制御 USBは同時押し6個まで、PS/2は無制限 この調整

メモ PS/2キーボードのUSB変換に関して

これまで調べたPS/2のスキャンコード、キー番号などに関する資料。

マイクロソフトの資料:
Enhanced Keyboards and Windows
Archive: Key Support, Keyboard Scan Codes, and Windows

キー番号、スキャンコードの組み合わせに関する説明:
Sazanami Online PS/2 インターフェイスの研究

Arduinoでキーボードをエミュレートする方法:
Arduino PS/2 Keyboard Emulator Issues
Arduino Forum › Hardware › Interfacing › Arduino as Keyboard

ArduinoをUSBキーボードにする方法:(Leonardo,Atmega32U4以外を使った方法)
Project Log : Arduino USB
Virtual USB Keyboard
practicalarduino / VirtualUsbKeyboard
Arduino Uno DFU プログラミング

 Arduino Leonardoは keyboard.press()とkeyboard.release()を使えば簡単にUSBキーボードをエミュレートできる。ただしUSキー配列なので変換テーブルなどが必要。
 PS/2のスキャンコードは可変長なのでやや扱いにくい。OADGでPS/2キーボードのキートップに対してキー番号が割り当てられているので、これを使えばすっきりする。
 だが、組み込み用途ではスキャンコード→キー番号→USBと変換すると冗長になる。今まで調べた例だとPS/2のスキャンコードからUSBのコードやASCIIコードに変換テーブルなりswich~case文で変換しているが、特殊キーや日本語配列の対応が考慮されていないため難しそう。そこでPS/2のスキャンコードを2バイトで表現し固定長にして、ASCIIコードやUSBのコードに変換しようと考えている。
例:1バイト目のbit7…make/break、bit0…拡張コードかどうか、2バイト目…スキャンコード
これだとスキャンコードの変換はほぼ流用できる。バッファは倍になるが、PS/2キーのバッファは16バイトなのでこれが32バイトになるだけ。

できるだけ再利用しやすい方向で考えたい。 

PS2KeyboardExt2の確認

以前PS2Keyboardライブラリを試したが、PS2KeyboardExt2というのもあったので試した。

http://arduino.cc/playground/Main/PS2KeyboardExt2 目的としてはPS2Keyboardの代替としてCTRLやALTなどの修飾キーの取得とコードサイズの縮小を目的としたものらしい。ソースはそのまま貼り付けてあるだけなので以下の様にライブラリに置いた。
(1)librariesディレクトリ以下にPS2KeyboardExt2というディレクトリを作る。 
(2)PS2KeyboardExt2ディレクトリ以下にPS2Keyboard.cppとPS2Keyboard.hをコピペして置く。
(3)PS2Keboard.cppのソース中"Wprogram.h"を"Arduino.h"に修正。(Arduino IDE1.0用)

もしPS2Keyboardライブラリをインストール済みだったら競合するのでディレクトリごとどこかに退避しておく。

 配線はPS2CLK(pin5)がArduino UNOのpin3、PS2DATA(pin1)がArduino UNOのpin4に接続。
サンプルスケッチをコピペして開き、動作を確認。
サイズは以下のとおり。
 Binary sketch size: 5170 bytes (of a 32256 byte maximum)
 修飾キー(CTRL,ALT)が取得できなかったのは?だが、これを元に動作を追いかけてみる。

ArduinoにPS/2日本語キーボードをつなぐ

ArduinoにはPS/2キーボードを接続するライブラリがオプションであるので実験してみた。

 まずPS/2キーボードを接続するための治具。以前PS/2信号の観測用に作ったものを手直し。

PS2jig2

Pin1(DATA)とPin5(CLK)について、10KΩでPin4(+5V)にプルアップ。ジャンパで設定可能。

PS2jig0

ピンの番号は写真の通り。

PIN1→Arduino Pin2、PIN3→GND、PIN4→5V、PIN5→Arduino Pin3 に接続。

なお、キーボードのCLKを割り込みとして受け付けて処理するので、Arduino UNOの場合はPin3にしか接続できない。

 ではPS/2キーボードのライブラリを設定してみる。Arduino IDEには標準では入っていないので自分で入れる必要がある。
 ARDUINO PLAYGROUND - PS2Keyboard
ここを辿っていくと
PJRC Teensy PS2Keyboard Library
があるので、ここのPS2Keyboard.zip (ver2.3)をダウンロード。

展開すると以下のような構成になっている。
PS2Keyboard¥
keywords.txt
PS2Keyboard.cpp
PS2Keyboard.h
  examples¥
  international¥international.pde
  Simple_test¥Simple_test.pde

このPS2KeyboardフォルダをそのままArduino IDEのlibrariesフォルダの下にコピーする。
Arduino IDEを立ち上げ、Simple_test.pdeを読み込む。

以下、スケッチを修正。
const int DataPin = 2;
const int IRQpin =3; 

ビルドして転送が完了すると、キーボードの入力をターミナルに表示する。Arduino IDEのターミナルはウィンドウ右上の虫眼鏡みたいなアイコンをクリックすると出てくる。
シリアル通信を使っていると、USBケーブルを外したりするとArduino IDEからCOMポートが見えなくなってしまうらしい。この様な場合はWindowsを再起動して対処した。 

 さて、これで確認できるのはUSキーボード配列だが、ライブラリを見てみたら日本語キーボードにも簡単に対応させることができそうだ。すでにドイツ語キーボードの対応が入っているので、ここを参考にすればいけそうな感じ。

 で、作ってみた。PS2Keyboard.cppとPS2Keyboard.hを以下と差し替える。
https://gist.github.com/2334909

使い方はスケッチ内で以下のようにする。
keyboard.begin(DataPin, IRQpin, PS2Keymap_Japanese);

 これでPS/2キーボードが使えるようになった。ただしPS/2テンキーのみの製品は正しいコードが反映されなかったり、応答しなかったりしたので後で調査する。
 ドイツ語配列を元に修正しているので、Altキー修飾はそのままでサボっている。気が向いたらカナにも対応したい。

チェックに使用したキーボード:
USキーボード Microsoft Natural Keyboard Elite
日本語キーボード SANWA SKB-108L 日本語108キーボード
PS/2テンキー IBM KeyPadIII P/N 79F6401 ×応答せず 、FUJITSU FMV-NTKB1 テンキーボード ×コード化け
 

PS/2キーボード変換器の製作(8)

Arduino Unoで試作し、Davinciに実装する方針にした。
(1) PS2Keyboardライブラリでキーボードが扱えることを確認
(2)USB HID Keyboardデバイスにできることを確認
(3)US→JPのマッピングを行う(PS2Keyboard.cppの修正)
でやってみる。

資料メモ:
PIC AVR 工作室 ブログ
ARDUINO PLAYGROUND PS2Keyboard
Interfacing the PS/2 Keyboard
PS/2 Keyboard Library
Virtual USB Keyboard

(1)の注意点:プルアップ抵抗が必要
(2)の注意点:DavinciのUSBインターフェースがよくわからないのでソフトウェアによるV-USBを使う
(3)の注意点:US配列とGerman配列があるので、ここを修正
記事検索
プロフィール

hardyboy

カテゴリ別アーカイブ
月別アーカイブ
QRコード
QRコード
  • ライブドアブログ