Bluetoothは、1つの周波数を使って通信するのではなく、ある程度の範囲の周波数をチャネルに区切り、動的にチャネルを切り替えながら通信を行うらしい。
これを「ホッピング」などと呼ぶそうだ。
あまりわかっていないので、調べておこう。
Core_V4.1[pdf]が出てるけど・・・まだCore_V4.0[pdf]の資料で見ていきます。
BLEは、チャネルが40(0~39)ある。
そのうち、37, 38, 39chはAdvertising専用。
残りの0~36chがデータ通信用。
(Core_V4.0[pdf] p.2199)
RFのチャネル番号と、Data/Advertisingのチャネル番号は異なるようだ。
以下は、Data/Advertisingのチャネル番号で表現しよう。
PDUの種類も、Advertising channel用とData channel用の2種類に分かれている。
今回調べたいものは通信中だから、Data channel用のPDUになる。
channel selection algorithm
(Core_V4.0 p.2239)
(Core_V4.0 p.2212)
Data channelは37個あるが、それは状態を持っているようだ。
状態のテーブルがあって、"used"とか"unused"とかが割り当てられている感じがする。
次に使うチャネル番号を決めるときは"unused"となっているものの中から選んでいくけど、37回やると全部"used"になってしまうから、計算式で計算されたチャネル番号の状態を"unused"に戻していく。
それを「channel selection algorithm」と呼んでいるのだろう。
channelについては、「4.5.8.1 Channel Classification」に説明があった。
Data channelは「used channels」(used for the connection)と「unused channels」(not used for the connection)があり、これを「channel map」と呼んでいるそうだ。
used=使ってよい、unused=使うな、という意味か。
そして、used channelsの最小数は2、とある。つまり、最低でも2ch分は空いていないといかんということか。
このmap情報は、Link層が管理していて、masterが用意し、slaveはそれを受けとって使うそうだ。
最初は、CONNECT_REQ PDUに載せ、変更するときはLL_CHANNEL_MAP_REQ PDUを使うみたい。
数式としては以下の2つだけだ。
unmappedChannel = (lastUnmappedChannel + hopIncrement) % 37 ... (1)
remappingIndex = unmappedChannel % numUsedChannels ... (2)
"unmappedChannel"は、現在のところ未割り当てになってるチャネル番号。
上記の計算で、次に未割り当てにするチャネル番号を決める。
"lastUnmappedChannel"は、文字通り、最後に「unmapped」にしたチャネル番号で、最初は0。
1イベントが終わったら、式(1)でunmappedChannelを計算する。
unmappedChannelの状態が"used"だったら、そのチャネル番号をData channelとして使う。
状態が"unused"だったら、式(2)でremappingIndexを計算。
この"remappingIndex"は状態のテーブルとは別で、"used"になってるチャネル番号のものを集めたテーブル用の番号だ。
そのテーブルからremappingIndexのところにあるチャネル番号をData channelとして使うことになる。
訳してみたが、あってるだろうか?
実際に計算してみよう。
37チャネルでやると大変だから、5チャネルにしてやってみるか。
hopIncrement=1にしておこう。
mapped | 0 | 1 | 2 | 3 | 4 |
state | used | used | unused | unused | used |
まず、最初はlastUnmappedChannelが0なので、0chを使う。
mapped | 0 | 1 | 2 | 3 | 4 |
state | used | used | unused | unused | used |
0chが終わったので、計算。
unmappedChannel = (0 + 1) % 5 = 1
次は1chを使う。
mapped | 0 | 1 | 2 | 3 | 4 |
state | used | used | unused | unused | used |
1chが終わったので、計算。
unmappedChannel = (1 + 1) % 5 = 2
あら大変、2chは「unused」だ。
このときは式(2)を使う。
remappingIndex = 2 % 3 = 2
remap | 0 | 1 | 2 |
ch | 0ch | 1ch | 4ch |
remappingテーブルの2番目は4chなので、次は4chを使う。
mapped | 0 | 1 | 2 | 3 | 4 |
state | used | used | unused | unused | used |
4chが終わったので、計算。
unmappedChannel = (4 + 1) % 5 = 0
また0chに戻る。
そんなわけで、ホッピングするチャネルを知るためには、masterからslaveに渡されるチャネルマップとhopIncrementを取得すれば良いことになる。
CONNECT_REQ PDUなるものがあるらしいので、見ておこう。
これは接続時のものなので、Advertising用のPDUだ。
(Core_V4.0 p.2206)
(Core_V4.0 p.2207)
ここの、ChMとHopがそうだ。
5octで40bitだから、それぞれに1/0を立てていくんだろう。
では、SensorTagで実際にキャプチャしてみよう(iPad mini old)。
最初が1Fだから、3bit分抜かれている。Advertising用だろうな。
37~39chなので一番最後だが、Bluetoothは並びがLittle Endianだから、先頭のb7~5ビットに0が入っているのだろう。
hopIncrementは8。
8 --> 16 --> 24 --> 32、ときて、次は40だけど37でmoduloして余りが3だから、3ch。
うん、解釈は間違ってないようだ。
0 件のコメント:
コメントを投稿
コメントありがとうございます。
スパムかもしれない、と私が思ったら、
申し訳ないですが勝手に削除することもあります。
注: コメントを投稿できるのは、このブログのメンバーだけです。