NEC PC-8001/88/98シリーズ配列テンキーの作成(その5)
Pro Micro(Arduino Leonardo)対応編4(2018/7/27 - 8/12)

戻る

1.未実装な機能と改良点

ブレッドボードでの試作では、MODEキーによるJIS/USコード環境の切り替え等が未実装でした。
まずは、その点の実装と、改良点としてチャタリング対策の検討をしてみました。

また、そもそも、使いやすいテンキーとは何ぞや?と言うことで、色々なキーワードで調べたところ、
テンキー選びのポイントというメーカーのページで「NumLockキー・非連動タイプ」との記述を見つけ、
これも検討候補に入れてみることにしました。


2.キーマップ切り替えとモード変更制御

と言っても、制御としては、キーマップを3面定義にして、MODE1~MODE3キー押下時にそれらを
切り替える処理を実装するのみですので、それほど難しい話ではありません。
JIS/US環境でのキーコードの違いも同様ですが、これらの問題を検討する前にキーマップを
決定して置いたほうが良さそうです。

○キー配列
試作1号の実績も含め、もともとの目標の「NEC配列を踏襲しつつ実務で使いやすい」と言うことで、
概ね下記に落ち着きました。

まあ、回路図の通りなのですが。

下側の20キーは、カッコ()を配置した以外は、PC-9801やPC-8801シリーズと全く同じキー配列です。
最後まで悩んだ(まだ迷っている)のは「電卓」キーと「TAB」キーとのトレードオフでしょうか。
試作1号を制作した際にHELPキー代わりに「電卓」キーを設けてみたところ、思いのほか使い勝手が
良かったため、そちらを優先していますが、今後、Excelでのセル移動などを多用する機会が増えて
くるなどしたら、再考しようと思います。

と言いつつ、スケッチのキーマップを書き換えるだけ(数分)で対応できますので、あまり深刻な問題
ではなさそうです。(自分で制御ファームもカスタマイズできると本当に便利ですね)

○JIS/USコード切り替え
次に、JIS/USコードの話ですが、なんでこのような切り替えを行いたいのかというと、
自宅で使っているGPD WINや海外製のWindowsタブレッドに日本語キーボードを接続すると、
「Shift」+「2」で「@」が入力されたり、「^」キーの入力が「=」になってみたりと、
USキーボードとして認識されてしまう現象があります。

今回のテンキーで言えば、カッコの入力は日本語(JIS)環境なら、「Shift」+「8」と「Shift」+「9」で
行えますが、上述のUS環境では「Shift」+「9」と「Shift」+「0」を押下する必要があります。
イコール「=」キーの入力も同様で、日本語(JIS)環境なら「Shift」+「-」ですが、US環境だと
「^」キーを押す必要があります。

少々わかりづらいので、一覧にまとめてみました。
HID仕様書(Hut1_12v2.pdf) の53ページから記載の一覧を参考にしています。

(1)標準KEYPAD(テンキー)対象キー
まず、標準テンキーの配列に関しては、JISとUSで差異はありません。
特に何もせず、そのままKEY CODEを送付すれば良さそうです。
日本語(JIS)英語(US)HID仕様説明
入力文字KEY CODE差異なし○
NumLockNumLock0x53
//0x54
**0x55
--0x56
++0x57
EnterEnter0x58
1(End)1(End)0x59
2(↓)2(↓)0x5a
3(PgDn)3(PgDn)0x5b
4(←)4(←)0x5c
550x5d
6(→)6(→)0x5e
7(Home)7(Home)0x5f
8(↑)8(↑)0x60
9(PgUp)9(PgUp)0x61
0(INS)0(INS)0x62
.(Del).(Del)0x63

(2)標準KEYBOARD(Shift操作)対象キー
今回のテンキーで追加するカッコ、カンマ等を抜粋しました。
日本語(JIS)英語(US)HID仕様差分
JIS+ShiftUS+ShiftKEY CODE○/×
8(8*0x25×
9)9(0x26×
00)0x27×
EscapeEscape0x29
BackSpaceBackSpace0x2a
TABTABTABTAB0x2b
-=-_0x2d×
^~=+0x2e×
,<,<0x36
Shift制御が必要なKEY CODEに差異(差分×)があり、送出するキーコードと
その際のShiftコード付加の条件を変える必要がありそうです。

○JIS/US対策
・JIS/USで差分があるキーコードは、別のキーコード(+Shift修飾)を定義して、別マップで管理する。

と、最初の方針と同じでスミマセン・・。


3.チャタリングの抑制

ブレッドボードでの試作では、たまにキー入力が一度の押下で2文字送られてしまうことがあり、
チャタリングの対策を行う必要を感じました。
とは言え、結局のところ、キースイッチのメカニカル接点の振動によるものなので、
原理的には、その振動が収まるまで待ってから、キー状態を再度読めば、大丈夫と言えます。

既にキー状態を読む際に「前回と今回で違いがあったら動作する」条件を入れてありますので、
あとは「少し時間を待ってもう一度読む」処理を入れれば良さそうです。

あまり難しく考えずに、5ms程度の周期で2度読みして、結果が一致したら有効なキー状態として処理してやる
こととして、キーI/Oを一定間隔でスキャンして有効なキーかどうか判定する処理(key_scan())と、
有効キー状態に変化があったら各キー動作を行う等の判定処理(key_check())と分けてみました。

結果から言うと、loop()を約5ms遅延を挟んで動作するようにしておいて、上述のkey_scan()の判定を追加すると
チャタリングの発生がほぼ抑制できました。(少なくとも単一押下で複数入力は発生しなくなりました)

ほぼ、と書いているのは、改良を加えるにつれ、チャタリングと疑われるような現象が出た際に、
本当にチャタリングが原因なのか、故障(はんだ不良)やキー操作が誤っていたのか等を切り分けるのが
困難になってしまったためで、最後は仕方ないので他社製の複数のキーボードで同様の操作をして、
入力ミス発生率をカウントする等の相対評価を行って「だいたい一緒だな」というレベルで終了としました。

これ以上は、タイピングが上手な人がシビアな条件で確認しないと難しいかもです。
(けっして諦めたわけではないのですが・・)


4.NumLockキー非連動と、Nキーロールオーバー対応について

前者は、使いやすいテンキーの必須機能として、後者は高級なキーボードの条件として挙げられることが多い機能です。

○NumLockキー非連動
テンキー選びのポイントより抜粋すると、
>ところが、一部のパソコンではこのNumLockキーが外付けテンキーのNumLockキーと連動してしまい、
>キー入力に不具合が生じます。そういったノートパソコン本体でも快適にテンキーを利用できるように
>作られたのが、「NumLock非連動タイプ」です。

と言うことで、基本的にはノートPC向けの使い勝手向上機能のようです。
最近発売されているテンキーは、ほとんどこのタイプのようで、複数メーカーの説明を読むと、
「テンキーを操作している間だけ、ホストPCをNumLock状態にする」と言う制御を行っているようです。
利用OS側に専用のドライバーを必要としないことから、 HID仕様書(Hut1_12v2.pdf) 通りの制御コードをテンキー側で
送付していると思われます。

整理すると、以下のような制御と推測できます。
・ホストPC側とは別に、テンキー側にもNumLock状態(モード変数)を持つ。
・テンキー側のNumLock状態と、ホストPC側のNumLock状態に違いがある場合は、テンキー操作
 (キーコード送出)の前後に、Numlock操作(code 0x53を、press/release)を行う。
・テンキー側のNumLock状態と、ホストPC側のNumLock状態が一致している場合は、Numlock操作は行わない。

Shiftコード付加と似たような制御ですので、実装はできそうです。
しかし、NumLock操作がキー押下ごとに行われますので、ゲーミング向けにプログラマブルテンキー的な
使い方をする場合(私のようにPC-8001ゲームがやりたい等)には、邪魔になりそう。

特にハードなゲームプレイでテンキー側とホストPC側のキーをガシガシ同時押下する場合に、
ホストPC側とは非同期に(=テンキー側の都合で)勝手にNumLock設定や解除をされるのは、
なんだかまずそうな気が・・。

・結論
 コンパイルスイッチを設けて機能をON/OFFできるような実装にします。

○Nキーロールオーバー対応
wikiによると、Nキーロールオーバーとは、
「複数のキーを同時に押したとき全てのキー入力が認識される機能のこと」のようなんですが、
USBデバイスの場合、HID通信の規格として6文字までしか操作できないとの意見もあります。

実際にHIDライブラリの HID_KeyboardReport_Data_tの定義を見ると、確かに6文字なようなので、
少々微妙な感じなのですが、ライブラリのexamples(NKROKeyboard.ino)を見ると、
キーコードの送付にNKROKeyboardクラスの関数を利用するとライブラリレベルで対応できるとのこと。

・クラス初期化関数
 NKROKeyboard.begin();
・キー押下(add)
 NKROKeyboard.add(KeyboardKeycode(CODE));
・キーリリース(remove)
 NKROKeyboard.remove(KeyboardKeycode(CODE));
・キーコード送付(send)
 NKROKeyboard.send();

見たところBootKeyboardクラスと制御は同じです。つまり関数を置き換えるだけで良さそうです。
これでカタログスペックだけは、高級機に迫れそうです。

全てライブラリ任せですが・・。(本件はこれ以上深く追及しないことにします)


5.スケッチの実装について

というわけで、色々盛りだくさんな改良を施したスケッチが下記です。

(うまくソース表示されない人はこちらからどうぞ)

ほとんど原型を保っていません。(動作検証時の苦労が・・)
実装機能については、詳細なコメントをスケッチに書いておいたので、そちらを参照いただくこととして、
コンパイルおよび、チューニングのポイントのみ、説明します。

○コンパイルオプションについて
NumLock非連動機能が必要な場合は、コンパイルオプション(__NUM_LOCK_UNSYNC)を0→1に変更して
コンパイルとボード書き込みを行ってください。
所有のSONY製、TOSHIBA製、DELL製のノートPCで動作検証をした限りでは、きちんと動作しているようです。

とは言え、上で述べた通り、ノートPC側のキーボードと、テンキーを同時にガシガシ操作をすると、
あまり好ましくない状況が生じるかもしれません。利用には十分な注意をお願いします。

○キー操作時のチャタリング制御について
チャタリングキャンセルのため、スキャン周期(KEY_SCAN_TIME)を5msにしています。

キー操作(まっすぐ押下or爪が引っ掛かった)等でも状況が変わりますが、1回の操作で複数回の
入力がされる等の症状が頻発する場合は、この値を増加させて(5→10など)様子を見てください。

逆に、操作したのに入力が抜ける場合は、この値を減らす等を試してみる事になりますが、
結構、キースイッチのはんだ付け不良ということがありました。(私の工作が悪いという話でした)
特定キーのみでチャタリングが発生する場合は、まずはその辺りのご確認をオススメします・・。

○キーリピート/Nキーロールオーバー対応について
基本的にライブラリ任せです。

○その他
1人で突っ走って実装したので、見落としや勘違いがあるかと思います。
何かお気づきの点がありましたら、スケッチにメールアドレスを記載しておきましたので、ご連絡ください。


6.動作モードの切り替えについて

各モードキー操作とキーマップの関係は下記のとおりです。LED表示色も連動して変わります。
キー操作MODE1 押下MODE2 押下MODE3 押下
対応キーマップ日本語(JIS)英語(US)ユーザー定義(J80用)
LED表示色黄色
MODE3は、完全に個人用になっていますので、もしこのスケッチを利用するような奇特な方がいましたら、
好きなキーマップに変更していただけると大変嬉しいです。

各モードでのLED表示状況です。

・JISモード(MODE1):LED緑点灯

テンキーを接続する(初回起動)かMODE1を押下すると、このモードになります。

・USモード(MODE2):LED青点灯

英語環境でキー入力が想定と違う場合にMODE2押下でこのモードになります。
英語Windows環境やAndroid環境で利用時に想定通りのキーが入力できることを確認しています。

・ユーザーモード(MODE3):LED黄点灯

MODE3押下でこのモードになります。
j80向けかつ、PC-8001アプリ操作用の専用モードです。ゆえに黄色(j80のスマイルアイコンと同色)です。
HOME CLRやINS/DEL含め、j80標準のキーアサインにハードウェアレベルで対応しています。
個人的には、このモードを実装するために作ったといっても過言ではありません。

GPD WINでもきちんと動作しています!

もう改良点もないはずなんですが・・(次回に続きます)


戻る