少し時間が空きましたが、後半をお届けします。


 BlueUSBは、BluetoothドングルによるWiiリモコンとの通信以外にもBluetoothマウスやキーボード、USBメモリ(マスストレージ)も扱えるようになっています。

sイメージ-1.jpg

 
 公開されているソース・コードを見てみるとそれらを実現するためにとても複雑なプログラムになっていますが、公開されているコードから学べることも多くあります。
 ここでは、ソース・ファイルの構成と簡単にBluetooth通信について説明します。

BlueUSBのファイル構成
 AutoEvents.cpp    USBイベント処理
 hci.cpp        HCI(USB-Bluetooth間のインターフェース)クラス
 hci.h            hci.cppのヘッダ
 hci_private.h        HCI処理のデバッグ・メッセージ出力用の定義と処理
 L2CAP.cpp        L2CAP(Bluetoothのデータ・リンク層プロトコル)クラス
 main.cpp        メイン処理とUSBファイル・システム定義
 MassStorage.cpp    USBマスストレージ・クラスの処理
 Socket.cpp        Bluetoothのリンク用ソケット・クラス
 Socket.h        Socket.cppのヘッダ
 TestShell.cpp        シェルやBluetoothのアプリケーション処理
 USBHost.cpp        USBホスト(OHCI)クラス
 USBHost.h        USBHost.cppのヘッダ
 Utils.cpp        デバッグ・メッセージ用のユーティリティ
 Utils.h        Utils.cppのヘッダ
 
 Bluetoothの通信はEthernetのように通信層が分かれていて、各通信層の中で用途に応じてプロトコルが分かれています。USBのBluetoothドングルの場合、mbedとの論理的な通信レイヤとWiiリモコンとの通信は以下のようなイメージになります。


sイメージ-2.jpg
 最終的にはWiiリモコンとHIDプロトコルで通信しているイメージとなります。
 ソース・コード上ではTestShell.cppの104行目にあるメソッドが、Wiiリモコンから受け取ったHIDパケットを解釈し、メッセージを出力している部分になります。
 Bluetooth  HIDプロトコルの受信でコールされる処理(TestShell.cpp 104行目~)
(説明のためコメントを追加しています。ブラウザ上で直接日本語は書けません。)

static void OnHidInterrupt(int socket, SocketState state, const u8* data, int len, void* userData)
{
        HIDBluetooth* t = (HIDBluetooth*)userData;
        if (data)
        {
            if (t->_devClass == WII_REMOTE && data[1] == 0x30)	// ---------------------------<<1>>
            {
                printf("================wii====================\r\n");
                t->Led();	// WiiリモコンのLED1を点灯させる。
                t->Hid();   	// Wiiリモコンに対して、ボタンと加速度センサの情報を送信
// するように指令する。
                t->_devClass = 0;
            }

            const u8* d = data;
            switch (d[1])
            {
                case 0x02:
                {
                    int x = (signed char)d[3];
                    int y = (signed char)d[4];
                    printf("Mouse %2X dx:%d dy:%d\r\n",d[2],x,y);
                }
                break;

                case 0x37: // Accelerometer http://wiki.wiimoteproject.com/Reports // ----- <<2>>
                {
                    int pad = (d[2] & 0x9F) | ((d[3] & 0x9F) << 8);	// ボタン
                    int x = (d[2] & 0x60) >> 5 | d[4] << 2;		// 加速度センサX軸
                    int y = (d[3] & 0x20) >> 4 | d[5] << 2; 		// 加速度センサY軸
                    int z = (d[3] & 0x40) >> 5 | d[6] << 2; 		// 加速度センサZ軸
                    printf("WII %04X %d %d %d\r\n",pad,x,y,z);
                }
                break;
                default:
                    printHex(data,len);
            }
        }
    }
 <<1>>の部分は最初にWiiリモコンから受信したときにWiiリモコンに対し、LED1(左端のLED)を点灯させて、ボタンと加速度センサの情報を送信するように指定します。それ以降は<<2>>の部分でWiiリモコンから受信した情報を分解し、ボタンと加速度センサの情報に分けてシリアル出力するようになっています。
 つまり、この部分でボタン情報や加速度センサ情報を見て何か動作するようにプログラムを追加するか別なクラスのインターフェースを用意して渡せば、いい訳です。
 Wiiリモコンのボタン情報はビット単位で表されています。ボタンとビットの割り当ては次のようになっています。(つづく)

sイメージ-3.jpg
 
勝純一





| | トラックバック(0)

トラックバック(0)

このブログ記事を参照しているブログ一覧: 壁を這うロボット <4>

このブログ記事に対するトラックバックURL: http://www.eleki-jack.com/mt/mt-tb.cgi/5513





カテゴリ


Copyright (C) 2006-2015 CQ Publishing Co.,Ltd. All Rights Reserved.