更新日: 2011 年 11 月 15 日
誤入力を回避する方法について
説明
KeyWitch.X の添付ドキュメントです。
KWTech.doc
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 誤入力の回避の方法について ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ X68000 のキーボードは初代機から単純なマトリクス構成になっているので、 3つ以上のキーが同時に押されたときに実際には押されていないキーが入力され てしまうことがあります。これが“ハード的な誤入力”です。ここでは、このプ ログラムの開発の経緯を辿りながら、KeyWitch がどのようにして誤入力を回避 しているのか説明します。なお、参考文献 [2] などでキーボードのマトリクス について知っておかないと、説明がよく理解できないと思います。誤入力に縁の ない人と、回避の方法に興味のない人は、お読みいただく必要はありません。 ┌───────────────┐ │1.誤入力の影響 │ └───────────────┘ X68000 PRO[HD] を使い始めて少しした頃、basic と入力したつもりが basioc になってしまったり、copy と打つと途中に x が混ざるという症状に悩まされま した。私よりも一足早く X68000 を使い始めた友達に相談し、その症状が故障で はなくて仕様であることを知ったとき、“本体の機能は凄いのにキーボードはち ゃちだ”と思えたものです。私が最初に登録したエイリアスは copy の代わりの cp でした。 その後、68000 のアセンブラで“画面に入り切らないプログラム”を書くよう になった頃、次の問題が発生しました。cmp と入力するとエディタの画面が1ペ ージ次に移ってしまうことが稀にあるのです。プログラムを作る思考の糸が切れ てしまって困りました。 かな漢字変換のローマ字入力でも問題が生じました。“しょ”と打つとそこま での入力を変換せずに確定してしまう症状です。他にも“おさ”が“おさい”に なったり“おしあ”になったりするなど、色々と不都合がありました。 ┌───────────────┐ │2.従来の対策 │ └───────────────┘ これらの問題については、“ハードウェアがそうなっているのだから仕方がな い”と諦めている人も多いと思います。解決策は、私の知る範囲では次の2通り がありました。 1つ目の解決策は、キーボードを改造してしまう方法です。誤入力は、同時に 押された3つのキーが他のキーの迂回路になっている場合に発生します。このと き、3つのキーの中の1つの接点に通常とは逆向きの電流が流れるので、ここに ダイオードを挟んでしまえば迂回路が断たれ、誤入力は発生しなくなります。し かし、業者のサービスでは PRO のキーボードは扱っておらず、自分でできる自 信もなければ代わりにやってくれそうな人もいないので諦めました。 2つ目の解決策は、キー入力割り込みルーチンに手を加えて、ソフトウェアで 3つまたは4つ以上のキーの同時入力を受け付けなくするものです。これは実際 に試してみたのですが、3つ以上受け付けない場合、誤入力を回避する効果より も実際に押したキーが入らない逆効果の方が気になり、かえってストレスが溜ま ってしまいました。また、4つ以上の同時入力を受け付けないのでは誤入力を回 避できず、例えば copy は coxy になってしまうことがあります。結局、この方 法で正しく入力するためには3つ以上のキーを同時に押してはならないことにな り、問題は解決されませんでした。 自明な解決策“3つのキーを同時に押さなければよい”も含めて、知り得る解 決策はどれも自分には得策ではないと思い、新たな情報を待っていました。 ┌───────────────┐ │3.挑戦 │ └───────────────┘ そして1年程前、Oh!X(参考文献 [2])にキーボードのマトリクス図が掲載さ れていたので、この問題に再び挑戦する気になりました。4つのキーが同時に押 されたとき、それが誤入力が発生する組み合わせかどうかを確かめて、もしそう ならば3番目に押されたキーと4番目に押されたキーをキャンセルすることにす れば、誤入力と関係ない場合までキーが入らないことはなくなると考えたのです。 このアイデアは、タイマー割り込みを使ってキー入力を遅延させるなどして実現 しました。その結果、確かに誤入力と関係ないキーの場合は正しく入力できるよ うになりましたが、これは誤入力を回避するという目的とは本質的に関係のない ことです。それなのにプログラムはかなり複雑になってしまいました。 さらにしつこく考えて、“同時に押されたとは考えにくいキーの組み合わせか どうか”を判定しようとしました。具体的には、“物理的に押しにくいキーの組 み合わせかどうか”と“英文やローマ字入力に現れない文字の組み合わせかどう か”の判定を試みたのです。しかし、判定のためのテーブルを作る段階で挫折し ました。ローマ字入力では“さい”と“さお”のどちらを入力しても“さいお” になってしまって見分けがつかないのです。 この頃、タイマー割り込みを使った関係で、誤入力のデータが入力されるタイ ミングの特性を調べてみました。誤入力のデータは3番目に押したキーの前後に ほぼ同時に入力されるはずです。しかし、3番目に押したキーのデータと誤入力 のデータの間隔は最大で約 10ms になっていて、実際に押されたキーの最小間隔 とほとんど区別がつきませんでした。 ここまでは、誤入力をキャンセルするために、キー入力をタイマーで遅延させ ていました。しかも、占有できて割り込み間隔も丁度よいタイマーがないので、 IOCS が使っている 10ms の Timer-C に寄生するという反則技を使っていたので す。これでは使える環境が限られてしまう可能性があります。それに、入力の間 隔を調べる方法を採るとしても 10ms では時間が長すぎます。Timer-C の割り込 み間隔を変えるという超反則技もありますが、さすがにひんしゅくを買いそうで す。そこで、タイマー割り込みを使わないでキー入力を遅延させるにはどうした らよいだろうかと考えました。 ┌───────────────┐ │4.新展開 │ └───────────────┘ このとき、ふとひらめいたことがありました。“キーを離すまで遅延する”と いう方法です。ちょっと大胆な案ですが、誤入力の可能性がない場合は遅延しな くてよいし、3つのキーを押さえてリピートさせることは SHIFT や CTRL 以外 ではほとんどなく、その SHIFT や CTRL では誤入力そのものが発生しない、と いう都合のよい条件が揃っています。入力の間隔を調べるにはカウンタだけ用意 すればよいので、遅延動作そのものにタイマー割り込みを使う必要はなさそうで す。 この案をもとに、誤入力の可能性がある場合に限ってキーを離すまで入力を遅 延するプログラムを作り始めました。迂回路上の3つのキーが同時に押された場 合、3番目の入力の直後に4番目の入力があるはずです。このとき3番目と4番 目のデータをキャンセルすればよいのです。更に、キーを押したときのデータを 取り除くのだから、3番目と4番目のキーが離されたときのデータも取り除くべ きだと考えました。そして… ┌───────────────┐ │5.呆気なく解決 │ └───────────────┘ ここで、とても重要なことに気付きました。誤入力は迂回路上の3つのキーが 同時に押されたときに発生します。すなわち、3つのいずれかが離されれば、そ れと同時に“実際には押されていなかったキーが離された”という誤入力も発生 するのです。この結果、次の事実が浮かびます。3つのキーが押されたタイミン グと離されたタイミングにそれぞれある程度時間差があって、その3つのキーが 1つの迂回路を構成していて、他に迂回路ができていない場合、迂回路上の4つ のキーの中で、誤入力は3番目または4番目に押されたキーのいずれかであり、 それと同時に1番目または2番目に離されたキーのいずれかでなければならない ということです。 3番目または4番目に押されたデータと1番目または2番目に離されたデータ に共通のキーがあるとしたら、それは何を意味するでしょうか。共通のキーがた だ1つだけあるならば、そのデータはほぼ間違いなく誤入力です。すなわち、こ の場合は誤入力のデータを特定することができます。もし2つのキーが両方とも 共通ならば、そのどちらが誤入力であるかわかりません。しかし2つのキーが共 通になるのは、同時に押された3つのキーの中で最後に押されたキーが最初に離 された場合だけです。普通にタイプしていればそのようなことはほとんど起こら ないと思われます。また、共通のキーが全くないのは3つのキーが同時に叩かれ たか同時に離された場合です。これらも普通にタイプしていればほとんど起こり ません(上記の記述には若干不完全なところがありますが、実用上の問題はない と考えています)。 結論として、“ソフトウェアでも、正確な迂回路判定と遅延入力を併用すれば、 たとえ誤入力が発生してもほとんどの場合はそれを回避することができる”ので す。 ┌───────────────┐ │6.誤入力を回避する方法 │ └───────────────┘ 後はプログラムを作るだけです。迂回路ができない場合と、誤入力を回避でき るほとんどの場合は問題ありません。気をつけなければならないのは、誤入力を 回避できない場合です。特に、キーボードの上に本が崩れてきたりして多くのキ ーが同時に押されてしまうと、絡み合った迂回路が幾つもできてしまいます。こ のような場合に誤入力の判定ルーチンがパニックを起こさないようにしなければ なりません。前述の方法をそのままプログラムにすると危なそうだったので、最 終的には次のように変形した方法を使っています。 『キー入力を遅延させるためにキュー(待ち行列)を使います。まず、キーが押 されたまたは離されたデータをキューに入れます。離されたときは、そのキーが 押されたデータがキューに残っていればそのキーを使って迂回路ができるかどう か調べ、できれば押されたデータと共にキューから取り除きます。最後にキュー の先頭のデータから順にそのキーを使った迂回路ができるかどうか調べ、迂回路 ができるデータの手前まで取り出して順にキーバッファに入れます。迂回路がで きるデータ以降がキューに残って遅延させられます。迂回路ができるデータがキ ューになければキューは空になります。キューが溢れた場合は、キューの先頭の データを取り出してキーバッファに入れます。』 やっていることはこれだけです。下手な説明だったと思いますが、意外に簡単 な処理で誤入力が回避できることがお分かりいただけたでしょうか。もっと詳し く知りたい人はプログラムを解析してみて下さい。 ──────────────────── ※参考文献は KeyWitch.doc をご覧下さい。 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ┌──────────────────────┐ │追加資料: Compact キーボードのキーマトリクス│ └──────────────────────┘ 下の表は、KeyWitch の作者が Compact キーボードにおける誤入力の入り方を もとに推定した、Compact キーボードのキーマトリクスです。ビットの順序は間 違いないと思いますが、スキャンラインの順序と番号が実際とある程度異なって いると思われます。しかし、迂回路を調べるだけなら、この表があれば十分です。 ─────────────────────────────────── BIT0 BIT1 BIT2 BIT3 BIT4 BIT5 BIT6 BIT7 ─────────────────────────────────── LINE2 → ← /? X V N ,< ─────────────────────────────────── LINE3 ↑ _ .> Z C B M ─────────────────────────────────── LINE4 ROLLDOWN ROLLUP ]} ;+ S F H K ─────────────────────────────────── LINE5 UNDO :* L A D G J ─────────────────────────────────── LINE6 DEL リターン @` O Q E T U ─────────────────────────────────── LINE7 HELP 記号入力 登録 F7 F1 F2 F3 F5 ─────────────────────────────────── LINE8 F9 F10 F8 COPY BREAK F4 F6 ─────────────────────────────────── LINE9 BS ^~ 0 8 ESC 2" 4$ 6& ─────────────────────────────────── LINE10 HOME \| -= 9) 1! 3# 5% 7' ─────────────────────────────────── LINE11 CLR [{ P I TAB W R Y ─────────────────────────────────── LINE12 ↓ XF5 XF4 XF1 XF2 スペース XF3 ─────────────────────────────────── ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ (EOF)