- 定数の定義
ポートに割り当てられたビットを定数として定義しておく。
- #define SYSTEM_LED 0x80000000
- #define PS_PAD_SEL 0x00100000
- #define PS_PAD_CLK 0x00020000
- #define PS_PAD_CMD 0x00080000
- #define PS_PAD_DAT 0x00040000
これによりどのビットを操作するのかわかりやすくなる。
- GPIO の1ビット入出力
LED を点けたりするのは 「組み込みプログラムのHello World !!」と呼ばれているが、それと同様である。任意のポートをOn/Off出来るプログラムを考える。LPC2138などの ARM系 CPU では IO0CLR, IO0SET を用いて以下のようにプログラムを書く。
IO0CLR = SYSTEM_LED;
LED は吸込みで点灯するので、ローにした時に点灯する。これは予め、マクロなどで定義しておくとプログラムの可読性が向上する。
#define LED_ON() (IO0CLR = SYSTEM_LED)
以後は LED_ON(); と記述すれば、OK。かなり読みやすくなる。同様に PS2 のコントローラの文脈で利用してみる。タイミングチャートによれば、PS2 コントローラの読み出しは SEL 信号が L になっているときに成立する。つまり、読み出し時は
IO0CLR = PS_PAD_SEL;
を記述する。その後にクロックを発生させ、それと同期してコマンドを発行すれば PS2 コントローラにコマンドが読み込まれる。そのコマンドの組み合わせにより、ボタンやスティックのステータスをホスト側に送信する。
- クロックの生成
クロックはポートの上げ下げで発生させる。つまり、ソフトで行う場合 IO0CLR / IO0SET 以上の速度は出せないので注意が必要である。また、このクロックを出している間は処理はブロックされていることも考慮する必要がある。
- コマンドの発行
コマンドは PS_PAD_CMD をドライブすることにより行われる。コマンドを発行するためにはそのコマンドのビット値を読んでから、それに対応したH/Lで信号線をドライブするわけである。実際にはこのように行う。
maskCmd = 0x01;
// Command line drive
if(maskCmd & aCommand)
IO0SET = PS_PAD_CMD;
else
IO0CLR = PS_PAD_CMD;
maskCmd = maskCmd << 1;
これを8回繰り返せば、1バイト分のデータを転送することが出来る。
- ポートの読み取り
ポートの読み取りは IO0PIN のステータスを読み出す事により行う。PS_PAD_DAT のステータスを読み出すわけである。
// Data line read
if(IO0PIN & PS_PAD_DAT)
readData = readData | 0x01;
readData = readData << 1;
これを8回繰り返せば、1バイト分のデータを読み出すことが出来る。
- データのシフト
- 初期化