Valid I/Q Samples For Angle Calculation
BLE规范定义了两个术语“Switch slot” 和 “Sample slot”。“Switch slot”和 “Sample slot”的长度必须相等,且只能设置两个值(1us和2us)。
在CTE开始时,要丢弃的元素数量取决于“Switch slot” 和 “Sample slot”的长度以及采样频率。
-
When using 1us slots:
- the guard period is 4us(guard period不采样/不需要丢弃任何样本)
- 参考周期是8us。在参考周期内采集的所有样本都必须丢弃(例如,如果采样频率为4MHz,则意味着必须丢弃32=8us x 4个/us 个样本-如果采样频率为1Mhz则必须丢弃8个样本)
- 第一个开关槽(和所有其他)持续1us。在一个开关槽期间采样的数据必须被丢弃(例如,如果采样频率是4MHz,这意味着在每个开关槽期间必须丢弃4个样本-如果采样频率是1MHz,每个开关槽必须丢弃1个样本)。
因此,当采样频率为4MHz时,首先考虑的是第37个样本。当采样频率为1MHz时,首先考虑的是第10个样本。
-
When using 2us slots:
- the guard period is still 4us (guard period不采样/不需要丢弃任何样本)
- 参考时间仍然是8us。在参考周期内采集的所有样本都必须丢弃(例如,如果采样频率为4MHz,则意味着必须丢弃32个样本-如果采样频率为1Mhz则必须丢弃8个样本)
- 第一个开关槽(和所有其他)持续2us。在一个开关槽期间采样的数据必须被丢弃(例如,如果采样频率是4MHz,这意味着在每个开关槽期间必须丢弃8个样本-如果采样频率是1MHz,每个开关槽必须丢弃2个样本)。
-
the sampling slots are divided in two:
1.一个1us的空闲槽(用来使天线稳定)。在空闲槽中采样的数据必须被丢弃(例如,如果采样频率是4MHz,这意味着在每个空闲槽中必须丢弃4个样本-如果采样频率是1MHz,每个空闲槽必须丢弃1个样本)。
2.一个1us的采样槽(例如,如果采样频率为4MHz,每个采样槽记录4个样本-如果采样频率为1MHz,每个采样槽记录1个样本)
因此,当采样频率为4MHz时,首先考虑的是第45个样本。当采样频率为1MHz时,首先考虑的是第12个样本。
下图展示了每个样本槽是如何划分的:
需要注意的是,只有天线能够切换并安置在小于1us的位置,才可以使用1us交换槽。如果天线不能切换和安置在小于1us的采样槽期间的部分数据将不正确,将不得不被丢弃。
确定I/Q样本的另一个好方法是绘制所有的I/Q样本。
下图显示了使用4MHz采样率和2us槽位的rtls_passive和rtls_master和rtls_slave的I/Q样本。
在没有天线切换的情况下,在参考周期内采集前32个(0~31)样本。因此,I/Q曲线看起来就像正弦波。
在第32个之后,你可以看到当切换发生时,I/Q样本出现了不连续。
当确实存在相位差时,比较容易看出相的不连续。因此,在采集I/Q数据前,请确保rtls_passive和rtls_slave的夹角不为0度。
Angle Compensation(角度补偿)
在AoA_getPairAngles()下,获得基于I和Q数据的相位差。之后,添加角度补偿。请看下面的代码。这是因为角度估计受天线对和频率的影响。p->gain, p->offset,channelOffset_A1和channelOffset_A2的值是基于实验室测量的。不同的天线板设计和频率会给你不同的p->gain, p->offset, channelOffset_A1和channelOffset_A2。下面的代码可以在AOA.c AoA_getPairAngles()中找到,这是天线对补偿。
// Write back result for antenna pairs
for (int pair = 0; pair < numPairs; ++pair)
{
const AoA_AntennaPair *p = &gAoaReport.antConfig->pairs[pair];
gAoaReport.antResult->pairAngle[pair] = (int)((p->sign * antenna_versus_avg[p->a][p->b] + p->offset) * p->gain);
}
正如你从上面的图中看到的,偏移量是用来确保在0度处接收到的数据在计算后会得到0度,然后改变斜率,使其更好地适应所有其他角度。
天线阵1的补偿值见:ant_array1_config_boostxl_rev1v1.c AoA_AntennaPair pair_A1[]
AoA_AntennaPair pair_A1[] =
{
{// v12
.a = 0, // First antenna in pair
.b = 1, // Second antenna in pair
.sign = 1, // Sign for the result
.offset = -5, // Measurement offset compensation
.gain = 0.95, // Measurement gain compensation
},
{// v23
.a = 1,
.b = 2,
.sign = 1,
.offset = -20,
.gain = 0.9,
},
{// v13
.a = 0,
.b = 2,
.sign = 1,
.offset = -20,
.gain = 0.50,
},
};
在天线对补偿的基础上,增加了频率补偿。对于天线阵1,用于频率补偿的值可以在ant_array1_config_boostxl_rev1v1.c int8_t channelOffset_A1[40]中找到。
int8_t channelOffset_A1[40] = {2, // Channel 0
2, // Channel 1
1, // Channel 2
1, // Channel 3
1, // Channel 4
1, // Channel 5
1, // Channel 6
1, // Channel 7
0, // Channel 8
0, // Channel 9
0, // Channel 10
3, // Channel 11
3, // Channel 12
2, // Channel 13
3, // Channel 14
3, // Channel 15
3, // Channel 16
3, // Channel 17
3, // Channel 17
3, // Channel 18
3, // Channel 20
3, // Channel 21
2, // Channel 22
3, // Channel 23
3, // Channel 24
3, // Channel 25
3, // Channel 26
3, // Channel 27
3, // Channel 28
2, // Channel 29
2, // Channel 30
2, // Channel 31
2, // Channel 32
2, // Channel 33
2, // Channel 34
2, // Channel 35
1, // Channel 36
0, // Channel 37
0, // Channel 38
0, // Channel 39
};
AoA Functions Overview
Here is the list of the most important functions for AoA users.
Python
-
aoa_set_params
:
class AoaSetParamsReq(NpiRequest, SyncReq, FromAp):
command = Commands.RTLS_CMD_AOA_SET_PARAMS
struct = Struct(
"aoaRole" / Enum(Int8ul, AoaRole), # AOA_MASTER, AOA_SLAVE, AOA_PASSIVE
"aoaResultMode" / Enum(Int8ul, AoaResultMode), # AOA_MODE_ANGLE, AOA_MODE_PAIR_ANGLES, AOA_MODE_RAW
"connHandle" / Int16ul,
"slotDurations" / Int8ul, # 1us/2us sampling slots
"sampleRate" / Int8ul, # 1Mhz (BT5.1 spec), 2Mhz, 3Mhz or 4Mhz - this enables oversampling
"sampleSize" / Int8ul, # 8 bit sample (as defined by BT5.1 spec), 16 bit sample (higher accuracy)
"sampleCtrl" / Int8ul, # sample control flags 0x0-default filtering, 0x1-RAW_RF no filtering
"samplingEnable" / Int8ul,
# 0 = mask CTE even if enabled, 1 = don't mask CTE, even if disabled (support Unrequested CTE)
"numAnt" / Int8ul, # Number of antennas in antenna array
"antArray" / Int8ul[this.numAnt], # GPIO's of antennas
)
slotDurations Setting
Value Description 2 2us for antenna switching and 2us for I/Q sampling. 1 1us for antenna switching and 1us for I/Q sampling.
Note:
对于选择slotDuration = 1的用户,需要确保自定义板上的RF开关能在1 us内稳定下来。
sampleRate Setting
Value Description 4 Process packets with AoA present in the header and sample CTE at 4 MHz. 3 Process packets with AoA present in the header and sample CTE at 3 MHz. 2 Process packets with AoA present in the header and sample CTE at 2 MHz. 1 Process packets with AoA present in the header and sample CTE at 1 MHz.
sampleSize Setting
Value Description 2 I/Q samples returned with 13 bits resolution. 1 I/Q samples returned with 8 bits resolution.
sampleCtrl I/Q data Filter Setting
bit[0] Description 1 BLE5-Stack returns whole I/Q data to the application. 0 BLE5-Stack filters out the I/Q data from switching period and returns the rest to application.
sampleCtrl Antenna Array Setting
bit[4:5] Description 0b01 Application use only antenna array 1. 0b10 Application use only antenna array 2.
Integration
发射载波频率+ 250khz tone(音频)的I、Q采样可以在主MCU不工作的情况下由射频核进行采集、预处理和缓冲。
对于rtls_passive, I/Q采样率目前不可配置, 固定为4Mhz。每个I/Q对在radio RAM中占用32位空间,radio RAM可以存储512个样本(即2048字节- 2 kB)。这种限制仅仅是由于微型堆栈限制了无线RAM中读取的数据量。无线电RAM长度为4 kB。
当采样率为4MHz时,每4us将有16个I/Q对,等于16 * 4(一个I/Q对占用4字节空间)= 64字节每4us。
这意味着即使CTE是160us长,4MHz采样率,rtls_passive的无线电RAM也只能存储I/Q数据,持续时间为128us。目前没有解决的办法,除非我们缩短CTE的长度。这对rtls_master来说不是问题。
Note:对于rtls_passive, I和Q样本只有13位的分辨率,即使它们占用RF核心RAM中的16位空间。因为它们只有13位的分辨率,你将观察到的有符号整数的最大值和最小值是[4095,-4096]。
对于rtls_master, I/Q采样设置是可配置的,从1MHz到4MHz。每个I/Q对在无线RAM中占用32位空间,无线RAM最多可以存储624个样本(2496字节-约2.5kB)。当采样频率达到最大值(4Mhz)时,在每个CTE中正好存储624个样本。(CTE持续160us,减去4us的守卫时间。当采样频率为4Mhz时,在156 us中存储156*4 = 624个样本。更多细节可在有效I/Q样本中提供,用于角度计算。)
对于rtls_master, I和Q样本分辨率是可配置的,请参见sampleSize设置。您可以选择只有13位分辨率的16位或8位分辨率,这是蓝牙核心规范版本5.1标准。选择哪个分辨率无关紧要,每个I/Q对总是在无线RAM中占用32位空间。
应用层将天线切换表传入射频核,射频核在采集I/Q样本的同时进行天线切换。
在从机中,射频核心保证CTE被插入到连接事件包的末尾而不被白噪声滤波器扭曲。
在passive 和 master 中,射频核心分析数据包并在同步天线切换时在正确的时间开始捕获样本。样本留在RF核心RAM中,由主MCU进行分析
AoA Driver
对于rtls_passive,一个使用Micro BLE Stack的例子,AoA驱动程序负责pin初始化,AoA启用,数据提取和角度估计。
rtls_master中的AoA功能实现为符合蓝牙核心规范5.1版,因此,初始化、支持AoA和数据提取都被移到主机模块。然而,用户仍然可以使用RTLS控制模块来设置需要的参数。
Configurations Supported
- Sampling frequency supported: 1 Mhz, 2 Mhz, 3 Mhz or 4 Mhz
- Sampling slot length supported: 1 us* or 2 us .注意:根据BLE规格,采样槽和交换槽必须有相同的持续时间。
- Sample size supported: 8bit or 16bit
Sampling slot of 1us is supported by the AoA driver but some limitations exist when using the BOOSTXL-AOA hardware. The antennas of the BOOSTXL-AOA require 1.6 us to switch and settle (leaving 0.4 us in the sampling period to collect data). Other designs with faster RF switches can support 1us switching.
Data Collection Flow
当RF Core检测到AoA包时,根据用户定义的周期切换天线的同时开始采样音频上的I/Q。
对于rtls_master, IQ样本将从RTLS服务主机模块发送到应用程序,事件类型为RTLSSRV_CONNECTION_CTE_IQ_REPORT_EVT。
根据python设置的AoA结果模式,调用不同的函数集并返回相应的数据集,如下图所示:
Note:对于rtls_master,当使用AOA_MODE_RAW时,如果sampleCtrl中的[0]位设置为0,则BLE5-Stack将过滤掉切换周期中的I/Q数据。要获得完整的I/Q数据集,需要将sampleCtrl中的[0]位设置为1。请参阅sampleCtrl I/Q数据过滤器设置概述。
Warning:对于rtls_master,当sampleCtrl= 1的[0]位时,不支持AOA_MODE_PAIR_ANGLE和AOA_MODE_ANGLE。
class AoaSetParamsReq(NpiRequest, SyncReq, FromAp):
command = Commands.RTLS_CMD_AOA_SET_PARAMS
struct = Struct(
"aoaRole" / Enum(Int8ul, AoaRole), # AOA_MASTER, AOA_SLAVE, AOA_PASSIVE
"aoaResultMode" / Enum(Int8ul, AoaResultMode), # AOA_MODE_ANGLE, AOA_MODE_PAIR_ANGLES, AOA_MODE_RAW
"connHandle" / Int16ul,
"slotDurations" / Int8ul, # 1us/2us sampling slots
"sampleRate" / Int8ul, # 1Mhz (BT5.1 spec), 2Mhz, 3Mhz or 4Mhz - this enables oversampling
"sampleSize" / Int8ul, # 8 bit sample (as defined by BT5.1 spec), 16 bit sample (higher accuracy)
"sampleCtrl" / Int8ul, # sample control flags bit[0] = 0-default filtering, bit[0]= 1-RAW_RF no filtering
# bit 4,5 - 0x10 - ONLY_ANT_1, 0x20 - ONLY_ANT_2
# 0x00 is not a valid option.
"samplingEnable" / Int8ul,
# 0 = mask CTE even if enabled, 1 = don't mask CTE, even if disabled (support Unrequested CTE)
"numAnt" / Int8ul, # Number of antennas in antenna array
"antArray" / Int8ul[this.numAnt], # GPIO's of antennas
)
当使用AOA_MODE_ANGLE时,天线图场必须为0、1、2,天线阵2时必须为3、4、5。
当使用AOA_MODE_RAW模式时,采样率固定在4MHz。
Connectionless AoA
为了不泛滥广告通道,connectionless AoA只被允许作为辅助包(即透过次要通道,参考 Bluetooth Core Specification Version 5.1 Vol 6, Part B, §2.3 for details on the PDUs allowed to be appended with a CTE
)。在BLE5-Stack中,支持周期性广告的无连接AoA