2015年1月12日月曜日

PS/2キーボードの波形に関して

しばらくキチガイじみたことを休止していたため、久しぶりの更新となります。

もちろん今もVimmerなわけで、もちろんUS配列信者でもあるわけで...
ついでに、大学のとある科目でマイコンを突っつく機会ができたわけで...

つまりですね、PSoCを使ってJISキーボードをUS配列風に変えたり、Vimエミュレータっぽい挙動をさせてみたりしてはどうかなと思ったわけです。

まぁ、それは良いとして、PS/2キーボードとしてマイコンが生成する信号をキーボードとしてちゃんと認識させるのに苦労しました。

PS/2キーボードのプロトコルに関してはこちらを参照しました。

これによると、clockがhighの時にdataをセットし、clockがlowの間にデータが読まれると言うこと。
つまりですね、clockがlowの時にはデータラインを変更しないということですよね。

しかし、まず苦労した点として、これを読まずに実装しに行ったのでどうせポジティブエッジだろうと勝手に思い込んでしまったんですね。
どちらかと言うとネガティブエッジなので失敗。
動作テストはキーボードの動きが見れれば十分だったのでBIOS上でやったのですが、ビープ音なりまくりw

そこで頼りになるのがオシロスコープ。
ちなみに、PS/2端子はOpen Drain Lowになっているのでオシロスコープにはプルアップ抵抗をつける必要があります。
とりあえずキーボードが生成する波形を測ってみました。
黄→データ
青→クロック
です(言わなくてもわかるか)



これはキーボードを話した時に送られる0xF0の波形。
スタートビット(常に0)、データビット(下位→上位ビットの順で送られることに注意)、パリティビット(奇数パリティ)、エンドビット(常に1)
の順で送られていることが確認できます。

で、

こっちがでっかくしたやつ。

よく見てもらうとわかると思うのですが(と言うか、0x0Fがわかりにくいのでもっとわかりやすい波形を使えって話なのですが、保存してあった画像がこれだけだったのですいません。)、
クロックの立ち下がりよりクロック周期の1/4だけ早くデータラインが変化しているのです。

というわけで、この波形を純粋に真似てみるということをしました。

そのソースの一部がこちら。

void outputData(BYTE d) {
    unsigned short i;
    unsigned short x = d << 2 | 0x03;
    int j;
    const t = 2;
    // calculate parity
    for ( i=0x80; i; i>>=1 ) {
        if ( d & i ) {
            x ^= 0x02;
        }
    }
    // send
    for (i=0x400; i; i>>=1 ) {
        if ( x & i ) {
            DATA_OUT_On();
        } else {
            DATA_OUT_Off();
        }
        for ( j=0; j<t; j++); // wait
        CLK_OUT_Off();
        for ( j=0; j<t; j++); // wait
        for ( j=0; j<t; j++); // wait
        CLK_OUT_On();
        for ( j=0; j<t; j++); // wait
    }
    DATA_OUT_On();
}


tの4倍がクロック周期となっていますね。
そもそも、マイコンのクロックが遅いのに対して、T=80[um]とかいう鬼畜な状況だったので、
データを送りながらパリティを送るのはリスキー。
そこで、先にスタート、データ、パリティ、エンドを羅列したxという変数を作成し、
そこから1bitづつ送信しています。
ちなみに、dは上位と下位を反転しています。

余談になりますが、キーボードの入力を読み取るときにクロックの立ち上がりで割り込み処理をしているのですが、80[um]ごとに11回連続で呼び出されることがわかっている割り込みなので、データをこねこねしていたのではとても間に合わないのかなぁと思って、論理演算のみで、しかも演算回数を極力減らしたかったので、オーバフローを活用しながら、上位と下位が反転した形でキーコードを扱うという非常に保守点検のしにくいプログラムが出来上がる予定です。


0 件のコメント:

コメントを投稿