ComProc PC/キーボード入力方式の検討
方式の検討
ソフトウェアでダイナミックスキャン
ソフトウェアでROW1~ROW8を順に走査し、COL1~COL8を読む
前回のスキャンとの差分を計算し、make/breakを検知
周辺回路は単純だが、ソフトウェア実装が面倒
単に「キー入力」したいだけなのに、やけに回路に密結合したソフトウェアを書く必要がある。
ソフトウェアで、キー位置(スキャンコードに相当)から文字(アルファベットや記号)に変換する必要がある
印字するために文字(ASCIIコード)が必要
専用回路でダイナミックスキャン
PC/AT互換機のキーボードコントローラ(KBC)的なもの
make/breakを専用回路が検出し、そのキーコードをキューに貯め、ソフトウェアが取得する
ダイナミックスキャンを行い、差分を検出する回路を作る必要があるが、ソフトウェアは単純化される
ただし、スキャンコードから文字に変換するソフトウェア機能は依然として必要
同一キーでも文字として異なるケースがあるので、スキャンコード=ASCIIコードとはできない
例えばASCIIコードでは「3」と「#」は異なる値だが、キーとしては同一
Shiftを押しながら「3」キーを押すと「#」となったり、ならなかったりする
どうしたいかはソフトウェアの都合なので、回路の方で勝手にShiftを解釈すべきではない
Shiftなどの修飾キーを完全に無視すればスキャンコード=ASCIIコードとすることは可能か?
専用回路を追加するなら、チャタリング抑制機能も組み込める
ソフトウェアでスキャンするなら、「連続N回オンならオン、N回オフならオフ」というようなロジックを(毎回)組む必要がある
多くのソフトウェアで共通で使う機能は基盤側(OSやハード)に持たせたい
スキャンコード=ASCIIコードとする試み
ASCIIコードは7ビット
未使用のビット8をmake/breakフラグとして使える
0=make
1=break
table:スキャンコード as ASCII
ASCIIコード 文字 キー
00 NUL
01 SOH
02 STX
03 ETX
04 EOT
05 ENQ
06 ACK
07 BEL
08 BS BS
09 HT Tab
0A LF Enter
0B VT
0C FF
0D CR
0E SO Shift
0F SI Caps Lock
10 DLE E/J
11 DC1 Ctrl
12 DC2 Alt
13 DC3 変換
14 DC4 無変換
15 NAK Kana
16 SYN
17 ETB
18 CAN
19 EM
1A SUB
1B ESC
1C FS Up
1D GS Down
1E RS Right
1F US Left
20 SPA Space
21 !
22 "
23 #
24 $
25 %
26 &
27 '
28 (
29 )
2A *
2B +
2C , ,
2D - -
2E . .
2F / /
30 0 0
31 1 1
32 2 2
33 3 3
34 4 4
35 5 5
36 6 6
37 7 7
38 8 8
39 9 9
3A : :
3B ; ;
3C <
3D =
3E >
3F ?
40 @ @
41 A A
42 B B
43 C C
44 D D
45 E E
46 F F
47 G G
48 H H
49 I I
4A J J
4B K K
4C L L
4D M M
4E N N
4F O O
50 P P
51 Q Q
52 R R
53 S S
54 T T
55 U U
56 V V
57 W W
58 X X
59 Y Y
5A Z Z
5B [ [
5C \ '\\' \ |(JIS配列「¥」)
5D ] ]
5E ^ ^
5F _ \ _(JIS配列「ろ」)
60 `
61 a
62 b
63 c
64 d
65 e
66 f
67 g
68 h
69 i
6A j
6B k
6C l
6D m
6E n
6F o
70 p
71 q
72 r
73 s
74 t
75 u
76 v
77 w
78 x
79 y
7A z
7B {
7C |
7D }
7E ~
7F DEL
KBC(キーボードコントローラ)の設計
一定時間ごとにROW1~ROW8を走査
1つのROWだけ0出力、その他はHi-Z
COL1~COL8はプルアップ入力
1つ前の状態をレジスタに保持しておき、現在の状態と比較
変化があればmake/breakコードをキューに追加
キューの深さは適当に決める
最初はN=1でもいいかも
ソフトがキューを読むたびにトップ値を返し、自動でpopする
キューが空なら0(NUL)を返す
スキャン周期とチャタリング
行と列のダイナミック接続なので、CRフィルタ+シュミットトリガを使ったチャタリング防止回路は組み込みなかった
FPGA側でチャタリングを防止する必要がある
スイッチ→チャタリング防止機構→KBC→ソフトウェア
何回も読んで安定するまで待つ方法
高速に何度も読み、N回連続でONならON、OFFならOFFと判定する方法
ON/OFFが入れ替わる間はKBCの入力を変化させない
ゆっくり読む方法
チャタリング継続時間より長い時間間隔でスイッチを読めばチャタリングに惑わされない
例えばチャタリングが8msくらいで収まるとすれば、10ms周期でスイッチを読む
仮にチャタリング中にスイッチを読んでしまったとき
スイッチを押した直後
1回目にONが読めた→2回目以降もONが読めるはず
1回目にOFFが読めた→2回目はチャタリングが収まっておりONが読めるはず→3回目以降もONが読めるはず
スイッチを離した直後
1回目にOFFが読めた→2回目以降もOFFが読めるはず
1回目にONが読めた→2回目はチャタリングが収まっておりOFFが読めるはず→3回目以降もOFFが読めるはず
ということで、最大20msは入力が遅延するものの、読んだ値がパタつくことはない
何回も読んで安定するまで待つ方法は遅延が少なく、回路が複雑
ゆっくり読む方法は遅延が大きく、回路が単純
遅延が大きいと言っても数10ms程度なので、まあ許容範囲か
メタステーブル
スイッチはFPGAのクロックに同期せず押されるので、メタステーブル対策が必要
チャタリングとは全然別の話
レジスタを列数分(8個)用意し、クロックに同期してCOLnの信号を取り込む
チャタリング防止機構はこのレジスタから値を読む
スイッチ→レジスタ→チャタリング防止機構→KBC→ソフトウェア