キーボードLEDの情報を取得する
NumLock,CapsLock,ScrollLockのLEDを制御します。今回一番苦労したところです。「LEDは付けない」という人には不要と思うかもしれませんが、テンキーの切替のためNumLockの情報だけは必要です。今回使用したキーボードはテンキーはありませんが側面に数字が印刷されたキーがあり、NumLockの状態によりキーコードを塗り替える処理を追加します。
LEDの情報はどう扱うのか
HIDの仕様書等参考資料によると、LEDの制御はデバイス側で行うのではなく、あくまでもデバイス側は押されたキーをホスト(PC)に送るだけでキーロックの状態はホストから送られて来る、と記述されています。SetConfigurationというコントロールトランスファで、エンドポイント0に1バイトのデータ(キーロック情報:下位5ビット)が送られて来ます。
SETUPstage:SETUPDAT[0..7]は、
| データ位置 | 内容 | 値 |
|---|---|---|
| SETUPDAT[0] | bmRequestType | (0x21) |
| SETUPDAT[1] | bmRequest | SET_REPORT(0x09) |
| SETUPDAT[2-3] | wValue | Report Type (0x02) Report ID(0x00) |
| SETUPDAT[4-5] | wIndex | Interface (0x00) |
| SETUPDAT[6-7] | wLength | Report Length (0x0004) |
DATAstage:EP0BUF[0]は、
| ビット位置 | Usageコード | 対応するLED |
|---|---|---|
| 0 | $01 | Num Lock |
| 1 | $02 | Caps Lock |
| 2 | $03 | Scroll Lock |
| 3 | $04 | Compose |
| 4 | $05 | Kana |
のようにホストからデータが送られて来ます。
取得の仕方
まず、dscr.a51にLED情報を得られるようにReportDscr(14行目と15行目の間)に書き加えます。
db 95h, 05h ;; REPORT_COUNT (5) LED out
db 75h, 01h ;; REPORT_SIZE (1)
db 05h, 08h ;; USAGE_PAGE (LEDs)
db 19h, 01h ;; USAGE_MINIMUM (Num Lock)
db 29h, 05h ;; USAGE_MAXIMUM (Kana)
db 91h, 02h ;; OUTPUT (Data,Var,Abs)
db 95h, 01h ;; REPORT_COUNT (1)
db 75h, 03h ;; REPORT_SIZE (3)
db 91h, 01h ;; OUTPUT (Cnst) LED report padding
SetConfigurationは、fw.cのメイン処理で捕捉され、bulkloop.cのDR_SetConfiguration(void)を呼び出しているのでこの中に処理を書きます。
BOOL DR_SetConfiguration(void) // Called when a Set Configuration command is received
{
Configuration = SETUPDAT[2];
if(SETUPDAT[0] == 0x21 && SETUPDAT[3] == 0x02){ //キーロック情報(Num,Scrlk,Capslk)取得
Test = 1;
EP0BCH = 0; EP0BCL = 0;
}
return(TRUE); // Handled by user code
}
フラグ(Test)を立てておき、このフラグが立っているときエンドポイント0にデータが来たときはLEDの情報だと判断します。EP0BCをリセットしていますがこうしておかないとデータが来ないようです。
次に、エンドポイント0出力の割込みを有効にします。fw.cの割込みの設定しているところに、
EA = 1; // Enable 8051 interrupts EPIE |= 0x02; //Enable EndPoint0 OUT interrupt. ←追加
のように追加します。そしてエンドポイント0出力の割込み処理ISR_Ep0out(void)に処理を書き加えます。
void ISR_Ep0out(void) interrupt 0
{
if(Test){ // キーロック情報(Num,Scrlk,Capslk)取得
lock_led = EP0BUF[0];
if(lock_led != lock_led_bak){
//lock_led b0:Num. b1:Caps. b2:Scroll.
//IOD.b4〜b6:LED出力用.0で点灯.下位4ビットに影響を与えない
OED = (OED & 0x0F) | ((lock_led << 4) & 0xF0);
lock_led_bak = lock_led;
}
Test = 0;
}
EZUSB_IRQ_CLEAR();
EPIRQ = 0x02; //Ep0out request clear
}
lock_ledにLEDの情報が取得され、Dポート(b4〜b6)に接続したLEDを制御します。
LEDの取り付け
ぎりぎりのサイズでケースを作ってしまってスペースが無いため、超小型のフルカラーLEDを使用しました。判り難いので市販のものには絶対採用されない方法ですがかえって手作りには面白いと思います。
USBキーボードの製作へ戻る
関連リンク
http://mcn.oops.jp/wiki/index.php?USB%2F%BB%C5%CD%CD
トップ メニュー
This web page is described in Japanese, but you can read in English by translation site.