マイコン ⇔ PS/2マウス・インターフェース


目  次

■概要
  ●送出コマンド(ホスト⇒マウス)
  ●マウスからの応答メッセージ(マウス⇒ホスト)
  ●ストリーミング・モード開始後の受信データ(マウス⇒ホスト)
■インターフェース回路の構成
  ●インターフェース回路
  ●プラグ/ジャック仕様
■信号のタイミング規定と送受信シーケンス
  ●マウスからのデータの受信タイミング
  ●マウスからのデータの受信シーケンス
  ●ホストからのコマンド送出タイミング
  ●ホストからマウスへのコマンド送出シーケンス
■プログラム解説
  ●ポート入出力用マクロ
  ●コマンド送出プログラム(put_mouse関数 .. 11〜50行目)
  ●データ受信プログラム(get_mouse1関数 .. 52〜94行目)
  ●ストリーミング・モード・データ受信プログラム(get_mouse3関数 .. 96〜114行目)
  ●マウスの初期化プログラム(init_PS2関数 .. 116〜125行目)
  ●ストリーミング・モード開始コマンド送出プログラム(start_PS2関数 .. 127〜134行目)
  ●メイン・プログラムの流れ
■応用に当たっての諸注意
  ●スクロール用ホィール付きマウスの場合
  ●2ポート(ホスト・マイコン側)による接続
  ●マイコンのクロック速度
■AVRマイコンによる実装例
  ●回路構成
  ●ソフトウェア1 ... 3ボタン・マウス用
  ●ソフトウェア2 ... ホィール・マウス用
■最後に

◆参考文献/URL
  (1)PS/2 technical reference manual October 1990 IBM Corp.
  (2)http://www.mcamafia.de/pdf/pdfref.htm
  (3)http://www.mcamafia.de/pdf/ibm_hitrc07.pdf
  (4)http://www.computer-engineering.org/ps2mouse/
  (5)特集*PCインターフェースの研究 第1章 キーボード&マウス・ポートの構造
    吉田功 トランジスタ技術 Oct. 1995


■概要
 マウスはコンピュータの入力機器として欠かせないものですが,マイコン応用システムにおいても2次元座標情報の入力として利用することができます.レーバー式のスイッチ操作と異なり,移動方向と移動速度の情報が入力できますので,マウスの操作速度により対象の速度を制御することが可能となります.このような対象としてゲームの入力機器やロボットの操作用の入力機器といった応用が考えられます.また,子供や高齢者,身障者が利用する装置のための「大まかな操作のための入力機器」としての応用も考えられます.

 
ここではPS/2マウスのためのインターフェース回路と制御ソフトウェアを解説します.最近のパソコンでは,USBマウスが主流になってきていますが,専用デバイスを使用したり制御が複雑なことが難点と言えます.これに対してPS/2マウスの場合は,インターフェース回路はいたってシンプルで,かつ,簡単なソフトウェア制御で利用することができるメリットがあります.
 以下では,ホスト側のマイコン・システムを単に
ホストと,PS/2マウスを単にマウスとします.また,クロック信号はマイコンのクロックと区別するため,マウス・クロック信号あるいはマウス・クロックと表記します.
 
ホストとマウスの間は,マウス・クロックとデータの2本の信号線による同期式双方向シリアル通信方式で接続されます.この2本の信号線は,ホストとマウスの両方が出力する双方向の信号で,両者ともオープン・コレクタ型のバッファで駆動するいわゆるワイヤードOR構成を取ります。
 送受信のデータは8ビット(1バイト)が1単位となります.送受信信号はスタート・ビットに続き,データ(LSBからMSBの順),奇数パリティ・ビット,ストップ・ビットが並びます.

 ホスト側からのデータの出力やサンプルはマウス・クロックに同期しておこないます.マウス・クロックの周期は最小60[μSec],最大100[μSec]と規定されており,マイコンのソフトウェアで制御可能な範囲にあります.また,
マウス・クロック信号は,ホスト側からの送信の最初(送信要求の通知)を除き,基本的にマウス側で生成します.

●送出コマンド(ホスト⇒マウス)

 マウスはホストに対してマウスの移動情報やボタンの操作情報を送出することが基本機能ですが,ホスト側から各種のコマンドをマウスへ送り.設定や制御ができます.主なコマンドを表1に示します.


 ここで,特に重要なコマンドはリセットとストリーミング・モード開始です.
 
マウスがリセット・コマンド(0xFF)を受信するとセルフ・テストし,初期化します.また,マウスはストリーミング・モード開始コマンド(0xF4)を受信することで移動情報やボタン操作情報の送出を開始します.

●マウスからの応答メッセージ(マウス⇒ホスト)

 表2にマウスからホストへ送られるメッセージの主なものを示します.


 
マウスはホストからのコマンドを受け付けると,応答メッセージ(0xFA)を返します.また,リセット・コマンドでは,応答メッセージに続き,セルフ・テストの完了を示す0xAAとマウスID(3ボタン・マウスの場合は0x00)を返却します.ストリーミング・モード開始コマンドでは,応答メッセージに続き,移動情報やボタン操作情報の送出を開始します.

●ストリーミング・モード開始後の受信データ(マウス⇒ホスト)

 
マウスがストリーミング・モードに設定されると,マウスは操作に対応した3バイトを1セットとした情報を送出します.マウスが送出するデータの形式を表3(1)(2)に示します.


 第1バイト目にはオーバー・フロー,移動方向,ボタンの状況などの情報があります.ボタンは押されている場合に1となります.ボタン操作に関しては,ボタンが押された時と離された時にマウスからのデータ送出があります.
 第2バイト目は横方向の移動量で,第1バイトのビット4の移動方向の情報(MSBとなる)と合わせて2の補数表示の9ビットの情報となります.したがって,移動量は−256から+255の値をとります.右方向への移動は+の値で,左方向の移動は−の値となります.
 第3バイト目は縦方向の移動量で,第1バイトのビット5の移動方向の情報(MSBとなる)と合わせて2の補数表示の9ビットの情報となります.同様に,移動量は−256から+255の値をとります.前方方向への移動は+の値で,手前方向の移動は−の値となります.


■インターフェース回路の構成

●インターフェース回路

 ホストとマウス間の信号はマウス・クロック信号とデータ信号の2本が基本となります.その他,マウスに電源を供給するための5[V]ラインとグランド・ラインがあります.図1にホスト・マイコンとマウスのインターフェース回路を示します.


 マウス・クロック信号とデータ信号は双方向の信号で,ホストからもマウスからも駆動される信号です.このため,通常のドライバICで接続することはできず,
オープン・コレクタ型のバッファ(7407など)で接続する必要があります.オープン・コレクタ型のバッファは出力部分にハイ・レベルを駆動するトランジスタがなく,出力端子を抵抗でプル・アップしておき,ハイ・レベルを確保します.つまり,オープン・コレクタ型のバッファ同士を接続しておき,いずれのバッファもロウ・レベルを出力しない場合,プルアップ抵抗の働きで信号ラインがハイ・レベルになる仕組み(いわゆるワイヤードOR)になっています.
 図1に示したインターフェース回路では,ホスト・マイコン側で,クロック信号を供給するポート(出力端子)にオープン・コレクタ型のIC(7407)を経由してマウスと接続し,マウスから送られてくるマウス・クロック信号は別のポート(入力端子)で受けます.データも同様に出力ポートにはオープン・コレクタ型を経由して接続し,データ入力は別ポートを割り当てています.

●プラグ/ジャック仕様
 次にホストとマウスを接続するプラグとジャックについて説明します.マウスのプラグは6ピンのミニDINでジャックはこれに対応するものを使用します(秋葉原などで容易に入手できます).図2に形状とピン接続を示します.


■信号のタイミング規定と送受信シーケンス
●マウスからのデータの受信タイミング

 マウスからホストへのデータ送出タイミングは,マウスが生成するマウス・クロックに同期して行われます(図3参照).



 マウスが送出するデータはマウス・クロックの立上がりエッジで変化します.データ変化のタイミング規定は最小で5[μSec],最大はマウス・クロックのハイ期間−5[μSec]となっています.
 したがって,
ホスト側はマウス・クロックの立下りエッジでデータをサンプルすることで,安定した後のデータを取得することができます.

●マウスからのデータの受信シーケンス
 マウスから送出されるデータをホストが受信するシーケンスはおよそ次のようになります(ホスト側の観点で説明).

マウスからのデータの受信シーケンス
@スタート・ビットの検出
 ・マウス・クロック入力ポートがハイ・レベルであることを確認
  −もしロウ・レベルであればエラーとする
 ・マウス・クロックのネガティブ・エッジを待つ
 ・データ入力ポートをチェックしロウ・レベルであることを確認
  −もし,ハイ・レベルであればエラーとする
Aデータの受信
 ・マウス・クロックのネガティブ・エッジを待つ
 ・データ入力ポートをサンプルし,受信データ(LSB)とする
 ・残りの7ビットのデータ(最後がMSB)について同様に繰り返す
Bパリティ・ビットの受信
 ・マウス・クロックのネガティブ・エッジを待つ
 ・データ入力ポートをサンプルし,奇数パリティを確認する
  −もし,1の数が偶数ならエラー
Cストップ・ビットの受信
 ・マウス・クロックのネガティブ・エッジを待つ
 ・データ入力ポートをサンプルし,ハイ・レベルであることを確認する
  −もし,ロウ・レベルならエラー
 ・マウス・クロック入力ポートがハイ・レベルになるのを待ち,終了


●ホストからのコマンド送出タイミング
 ホスト側からマウスへのコマンド送出は少々複雑です.最初にホスト側がマウス・クロック・ラインをロウ・レベルに設定することでマウス側にコマンド送出要求を伝え,それに対応してマウス側からマウス・クロック信号が出力され,それに合わせてホスト側がデータを出力します(図4参照).


 図4において,下段にあるマウス・クロックとデータのペアが信号線上の様子になります.分かりやすいように,中段にはマウスが出力する信号値を,上段にはホストが出力する信号値を示しています.

 
ホストはマウス・クロックの立下りエッジに同期してデータを出力します.マウスはマウス・クロック信号の立上りでデータをサンプルします.データはマウス・クロックの立上り後1[μSec]間は安定にする必要がありますが,マウス・クロックの立下りエッジに同期して出力していればこの規約は満足できます.

 
ホストが最後のストップ・ビットを送出した後,マウスはデータ・ラインをロウ・レベルにしてアクノリッジを返します.

●ホストからマウスへのコマンド送出シーケンス
 ホストからマウスへのデータ(コマンド)の送出のシーケンスをホストの観点から説明するとおよそ次のようになります.

ホストからマウスへのコマンド送出シーケンス
@ホストからマウスへの送信要求の伝達
 ・マウス・クロック出力ポートをロウ・レベルにする
 ・60から100[μSec]間待つ
 ・データ出力ポートをロウ・レベルにする(=スタート・ビット)
 ・マウス・クロック出力ポートをハイ・レベルにする
 ・マウス・クロックのネガティブ・エッジを待つ
Aデータの送出
 ・送出データのLSBをデータ出力ポートに出力する
 ・マウス・クロックのネガティブ・エッジを待つ
 ・残りの7ビットのデータについて同様に繰り返す
Bパリティ・ビットの送出
 ・1の数が奇数になるようにデータ出力ポートを設定する
 ・マウス・クロックのネガティブ・エッジを待つ
Cストップ・ビットの送出
 ・データ出力ポートをハイ・レベルにする
 ・マウス・クロックのネガティブ・エッジを待つ
D転送終了確認
 ・データ入力ポートをチェックし,ロウ・レベルを確認する(マウスの受信アクノリッジ)
 ・マウス・クロック入力ポートがハイ・レベルになるのを待って終了


■プログラム解説
 ここではアトメル社のマイコンAT90S4433(8[MHz])をターゲットし,C言語で記述したプログラムを例に解説します.なお,別のマイコンでも簡単に利用できるように,ポートの入出力部はマクロ化しています.
実際に使用するマイコンに合わせてマクロの変更や関数化するだけで対応可能になっています.AT90S4433用の実際のプログラムは後の節で紹介します.

〔リスト1〕PS/2マウス制御プログラム(行番号付き PDF)

〔リスト2〕PS/2マウス制御プログラム(行番号なし TXT)


●ポート入出力用マクロ
 表4にプログラムで使用しているポートの入出力マクロを示します.


●コマンド送出プログラム(put_mouse関数 .. 11〜50行目)
 「ホストからマウスへのデータ送出」で説明したフローにしたがって,プログラムを記述しています.リスト中のコメントの[1]〜[19]は図4の[1]〜[19]と対応しています.
 put_mouse関数は送信データを引数として受け取ります.put_mouse関数中の17行目のwait_60usec関数は60[μSec]間の待合せをする関数です.
 パリティは,データの送出毎にハイ・レベルであればカウントしておき,パリティ・ビットの送出時に奇数/偶数を判断し,ロウ・レベル/ハイ・レベルを送出しています.
 ストップ・ビット送出後はマウスからのアクノリッジ(データ入力ポートがロウ・レベル)を確認し,さらにマウス・クロックがハイ・レベルになるのを確認して終了しています.

●データ受信プログラム(get_mouse1関数 .. 52〜94行目)
 マウスから1バイト分のデータを受信する関数で,「マウスからのデータの受信」で説明したフローにしたがって記述しています.リスト中のコメントの(1)〜(16)は図3の(1)〜(16)に対応しています.
 get_mouse1関数は受信データの格納変数のアドレスを引数として受け取り,マウスからの受信データを格納します.また,リターン値としてエラー情報を返却します.
get_mouse1関数の呼出し時点ではマウス・クロックがハイ・レベルであることを想定しています.もし,マウス・クロックがロウ・レベルである場合はエラーとして終了します.
 パリティのチェックはデータの受信毎およびパリティ・ビットの受信時にハイ・レベルであればカウントしておき,関数の終了状態情報としてリターン値に設定します.
 ストップ・ビットの受信確認後,マウス・クロックがハイ・レベルになるのを待って終了しています.

●ストリーミング・モード・データ受信プログラム(get_mouse3関数 .. 96〜114行目)
 マウスをストリーミング・モードに設定すると,マウス操作に応じて3バイトの情報が送出されます.get_mouse3関数はこの3バイトの情報とステータス(エラー発生)を返却します.
 マウスの操作データを元におこなう主処理に時間がかかると,マウスは次の操作データを送出してしまうかもしれません.操作データの送出の途中から受信処理を開始すると,ホストは正常なデータを受信できません.そのため,
マウスの移動情報の3バイトを受信する場合は,マウスからの送信の途中の場合を検出して終了まで待ってから,新規に受信処理を開始するようにプログラムを作成する必要があります.リスト1のプログラム例では,101〜108行目において,マウス・クロックが一定期間ハイ・レベルであることを確認してから受信処理を開始するようにしてあります.

●マウスの初期化プログラム(init_PS2関数 .. 116〜125行目

 マウスの初期化プログラムはマウスをリセットするコマンド(0xFF)を送出し,マウスからのアクノリッジ・メッセージ(0xFA)を受信,次いでセルフ・テスト正常終了メッセージ(0xAA)を受信し,最後にマウスIDコード(0x00)の受信して終了します.この関数ではエラー情報を返却します.

●ストリーミング・モード開始コマンド送出プログラム(start_PS2関数 .. 127〜134行目)
 ストリーミング・モード開始コマンド送出プログラムはこのモードに設定するコマンドコマンド(0xF4)の送出し,マウスからのアクノリッジ・メッセージ(0xFA)の受信して終了します.この関数でもエラー情報を返却します.

●メイン・プログラムの流れ
 以上,説明したC言語関数を利用してメイン・プログラムを構成すると,次の様になります.

メイン・プログラムの流れ
@マウスのリセット
  init_PS2関数の呼出し
Aストリーミング・モードの設定
  start_PS2関数の呼出し
Bマウス操作データの受信と必要な処理
 ・マウスから3バイト受信
   get_mouse3関数の呼出し
 ・主処理を実行
 ・ループして繰り返す


■応用に当たっての諸注意
●スクロール用ホィール付きマウスの場合

 最近のマウスの多くはスクロール用ホィール付きマウス(以下,スクロール・マウス)になってきています.このスクロール・マウスを接続する場合は取り扱いが少々異なります.ポイントは次の3点です.

 ・ホィール機能を有効にしなければ,3ボタン・マウスとして機能
 ・よって,ホィール機能を有効するには設定が必要
 ・ホィールの回転情報は第4バイト目として付加


 ホィール機能を有効するには,ホストからマウスのストリーミング・モード開始コマンドを送出する前にサンプル・レイト設定として次の3パターン(10進数)を送出します.

  
200 ⇒ 100 ⇒ 80

 1つのサンプル・レイトのデータを送出した後,アクノリッジ・メッセージを受信してから次ののレイト・データを送信します.
 この設定を行った後,ストリーミング・モード開始コマンドを送出することで,ホィール機能が有効になります.
 ホィール機能が有効になると,マウスはホィールの動きの情報を第4バイト目に付加して送信してきます.第1から第3バイトの情報は3ボタン・マウスと同じです.第4バイト目の情報も2の補数で表現されており,ホィールを手前に回転させると+値となり,前方に回転させると−値となります.

●2ポート(ホスト・マイコン側)による接続
 ホスト側のマイコンのポートに3ステート・バッファを経由した出力機能があり,入出力の方向設定をプログラムによって動的に(プログラムの実行中にいつでも)切り換えられる場合,マウス・クロックの入力と出力ポートを1つのポートに集約して制御することができます.この場合,オープン・コレクタ型のバッファICも必要ありません.同様にデータの入力と出力ポートも1個のポートに対応させることができ,2個のポートでマウスを接続することができます.ただし,マイコンのポートのドライブ能力やマウスのケーブルの長さなどによっては,信号の送受に問題が発生することもあります.

●マイコンのクロック速度
 マウスで生成されるマウス・クロック信号は,ハイ・レベル期間,ロウ・レベル期間ともに最小値で30[μSec]と規定されています.ソフトウェアで制御する場合,必要な処理がこの期間内に終了する必要があります.低速なクロックでマイコンを動作させる場合や1命令に多くのクロックを要する初期のマイコンでは,30[μSec]間に必要な処理が終了せず,正常な送信/受信動作ができない場合があります.


■AVRマイコンによる実装例

 ここでは,アトメル社のマイコンAT90S4433(8[MHz])を使ったテスト・システムとC言語で記述したプログラムを解説します.ソフトウェアはC言語で記述し,GNUのAVR用gccであるwinavrでコンパイルしています.

●回路構成
 使用したマイコンはアトメル社のAT90S4433で,28ピンのスリムDIPパッケージの8[MHz]品です.動作確認用としてLCD(SC1602BS*B,16文字X2行),LED(2個),DIPスイッチ(2個)を搭載しています(写真1).マイコンAT90S4433の3つのポート(PB[5:0],PC[5:0],PD[7:0])を図5に示すように使い分けています.詳細な
回路図はこちらになります.



<写真1 AVR-PS/2インターフェース・テスト・システム>


●ソフトウェア1 ... 3ボタン・マウス用

 3ボタンのPS/2マウスの初期化をおこない,マウスからの操作データをLCDに表示するプログラムです.ファイル構成は次のとおりです.

ファイル名 内容 区分
AVRPS2_main.c メイン部 Cソース・ファイル
AVRPS2_mouse.c マウス制御部 Cソース・ファイル
AVRPS2_avrinit.c AVR初期化部 Cソース・ファイル
AVRPS2_timer.c タイマ部 Cソース・ファイル
AVRPS2_LCD.c LCD制御部 Cソース・ファイル
AVRPS2_swLED.c スイッチ・LED制御部 Cソース・ファイル
const.h 共通定数定義 ヘッダ・ファイル
avrps2.h 関数プロトタイプ宣言 ヘッダ・ファイル
mouse.h AVRポート制御マクロ ヘッダ・ファイル
LEDconst.h LED制御マクロ ヘッダ・ファイル
makefile コンパイル制御 makeファイル

 プログラムのコンパイルは上記全てのファイルを適当なフォルダにコピーして, make するだけです.


●ソフトウェア2 ... ホィール・マウス用
 こちらはホィール付きマウス用プログラムです.ほとんどの部分が上記3ボタン・マウス用と同じです.異なる部分は
 メイン・プログラム で,スクロール・モード用の設定コマンドとしてサンプル・レイトの設定部分があります.
 また,マウスからは4バイトが1パケットとして送られてくることになりますので,get_mouse3関数に替わり,get_mouse4関数があります(こちらも AVRPS2_main.c にあります).
 コンパイルするためには, AVRPS2_main.c を除く上記ファイル全てと,スクロール・マウス用メイン関数のあるファイル
(AVRPS2_main.c)を適当なフォルダにコピーして make します.

 次にAVR-PS/2インターフェース・テスト・システム上にホィール・マウスを接続して,マウスからの操作データを表示実験しているところの写真を示します.



<写真2 システム・テスト中の様子>

■最後に
 実は,このレポートの作成に先立ち,PS/2マウス・インターフェースをVerilog-HDLで記述して回路としてFPGAに実装しテストしています.準備ができ次第,公開する予定です.