BLE链路层信道选择算法浅析
Channel Map
Channel Map是标记了哪些信道用于数据连接,哪些信道不用于数据连接,我们知道BLE的数据信道包含物理信道0到物理信道36在内的共37个信道,下表是一个Channel Map的例子
物理信道号 | 是否使用 |
---|---|
信道0 | 使用 |
信道1 | 不使用 |
信道2 | 使用 |
信道3 | 使用 |
信道4 | 不使用 |
信道5 | 使用 |
... | ... |
信道36 | 使用 |
建立连接的过程中,发起者会向广播者发送连接请求(CONNECT_REQ),在这个连接请求中就包含了Channel Map,这个Channel Map是由发起者的应用层设置到链路层的。之后两个已连接的设备就使用这个Channel Map进行通信
HopIncrement
HopIncrement
是一个跳信道间隔值,它影响下一次跳频后所在的信道与当前信道的信道间隔。HopIncrement也包含在发送连接请求(CONNECT_REQ)的报文中。
信道选择算法
信道选择算法还涉及到另外两个变量:unmappedChannel
和lastUnmappedChannel
,它们之间的换算关系如下:
unmappedChannel = (lastUnmappedChannel + hopIncrement) mod 37
其中,设备建立连接后,lastUnmappedChannel初始化为0;当一个连接事件关闭之后,lastUnmappedChannel被赋值为unmappedChannel
得到unmappedChannel之后,如果unmappedChannel所指向的信道号在Channel Map列表里被标记为已使用,那么就用unmappedChannel作为本次连接事件的信道
如果unmappedChannel所指向的信道号在Channel Map列表里被标记为未使用,那么需要重新映射可用信道列表,那么什么是可用信道列表呢?
本文开头有一个Channel Map,那么这个Channel Map对应的可用信道列表如下表所示:
物理信道号 | 是否使用 |
---|---|
信道0 | 使用 |
信道2 | 使用 |
信道3 | 使用 |
信道5 | 使用 |
信道36 | 使用 |
可知这个可用信道列表只包含已使用的信道,那么重映射算法如下:
remappingIndex = unmappedChannel mode numUsedChannels
numUsedChannels
是可使用的信道的数量,也即是可用信道列表的长度(上表中为5个)。计算出的remappingIndex
作为可用信道列表的索引,例如,如果remappingIndex
值是3,那么查看上文中的可用信道列表可知,索引值3对应信道5,那么就把信道5作为本次连接事件使用的信道。
代码实现
下面用一个简单示例来描述这个算法:
#include <stdio.h>
int channelMap[] = {10, 21, 22, 23 };
int hopIncrement = 2;
int lastUnmappedChannel = 0;
int unmappedChannel = 0;
int remappingIndex = 0;
int channelSelection(void)
{
int numUsedChannels = sizeof(channelMap)/sizeof(int);
int channel;
unmappedChannel = (lastUnmappedChannel + hopIncrement) % 37;
for (int i=0; i<numUsedChannels; i++) {
if (unmappedChannel == channelMap[i]) {
channel = unmappedChannel;
goto exit;
}
}
remappingIndex = unmappedChannel % numUsedChannels;
channel = channelMap[remappingIndex];
exit:
lastUnmappedChannel = unmappedChannel;
return channel;
}
int main(void)
{
for (int i=0; i<5; i++) {
printf("Current Channel Index: Channel: %d\n", channelSelection());
}
return 0;
}
结果如下所示:
Current Channel Index: Channel: 22
Current Channel Index: Channel: 10
Current Channel Index: Channel: 22
Current Channel Index: Channel: 10
Current Channel Index: Channel: 10