本篇文章主要讲解如何将DCA1000采集的原始bin文件再matlab中解读出来,从而方便后续的数据处理,例如距离FFT、2D FFT等处理。在讲解之前,默认各位已经掌握了利用xWr1xxx mmWave +DCA1000通过mmWave studio采集原始数据,在本篇文章中不过多讲解,如果对与上述测数据的操作尚有不解可以参照此文档,mmWave_studio_user

一、xWR1xx With DCA1000 Data Format

要看深入理解原始数据通过matlab解读出来,清楚原始数据的输出格式是必不可少的。对于xWR16xx(xWr18x)/IWR6843设备,数据通过两个LVDS通道捕获,并以non-interleaved(非交错)格式存储在二进制文件中。DCA1000捕获的数据样本为2字节长,采用双补码格式。由于只使用了两个LVDS通道,xWR16xx(xWr18xx)/IWR6843无法使用3个接收器进行数据捕获。只能使用1、2和4启用的接收器。

 上图展示了四个接收器如何捕捉输出数据为实数数据的存储格式。每一个Chrip都按照接收器的顺序存储,从最低的接收器数开始,到最高的接收器数结束。LVDS Lane 1从每个接收器发送奇数个样本,LVDS Lane 2从每个接收器发送偶数个样本。如果总共有M个Chrip,则存储从第一个Chrip开始到第M个Chrip结束。对于任何禁用的接收器,可以从上图中的关系图中删除与禁用接收器对应的部分,以确定总数据输出。

对于输出数据是虚数数据时的格式如下;在这个图中,接收数据的bin文件中是按照non-interleaved模式来存储数据的,可以看到它lane1通道传输负责传输数据的实部,lane2负责传输数据的虚部,并且值得注意的是每个lane一次分别传输2个数据。

 二、matlab程序对原始数据的处理

我们采集的好的数据(这里用虚数举例)它是按照上述方式排列在一个bin文件中,对原始数据的解读就是将其分类,使其对应是那个接收机接收的数据。在上面我们已经提到,接收的数据是按照RX0将全部chrip信号接收完毕后,紧接着到RX1接收完毕,以此类推。接下来附上matlab解析源码,并解释部分代码。


function [retVal] = readDCA1000_1(fileName)
numADCSamples = 256; % 每一个chirp的采样点数
numADCBits = 16; % 配置ADC寄存器的样本点大小,有12、14、16bits可选择,这里选择为16bits
numRX = 4; % 接收天线的数量,本例中接收天线为4
numLanes = 2; % 这个是LVDS 通道数,对于xW18xx等,通道数只有lane1、lane2两个
isReal = 0; % 接收的数据类型(实数或者虚数,实数设置为1,虚数设置为0)
fid = fopen(fileName,'r');%%读取文件
adcData = fread(fid, 'int16')%%将文件所有数据导出为一个N维列向量
% 下面这个if结构是用来将数据大小小于16bits时的一个补偿,
if numADCBits ~= 16
    l_max = 2^(numADCBits-1)-1;
    adcData(adcData > l_max) = adcData(adcData > l_max) - 2^numADCBits;
end 
fclose(fid);
fileSize = size(adcData, 1);
if isReal
    numChirps = fileSize/numADCSamples/numRX;
    LVDS = zeros(1, fileSize);
    %create column for each chirp
    LVDS = reshape(adcData, numADCSamples*numRX, numChirps);
LVDS = LVDS.';
else
numChirps = fileSize/2/numADCSamples/numRX;
LVDS = zeros(1, fileSize/2);
counter = 1;
for i=1:4:fileSize-1
LVDS(1,counter) = adcData(i) + sqrt(-1)*adcData(i+2); 
LVDS(1,counter+1) = adcData(i+1)+sqrt(-1)*adcData(i+3); 
counter = counter + 2;
end
LVDS = reshape(LVDS, numADCSamples*numRX, numChirps);  
%each row is data from one chirp
LVDS = LVDS.';
end
adcData = zeros(numRX,numChirps*numADCSamples);
for row = 1:numRX
for i = 1: numChirps
adcData(row, (i-1)*numADCSamples+1:i*numADCSamples) = LVDS(i, (row-1)*numADCSamples+1:row*numADCSamples);
end
end
retVal = adcData;

在上述代码中,一部分代码已经被注释,接下来我将针对代码片段进行讲解它的功能。

  这个if语句主要用来检查lane输出的数据大小是否为16bit,如果不是将对其进行补偿。

fileSize = size(adcData, 1);%%计算数据个数
if isReal
    numChirps = fileSize/numADCSamples/numRX;%%确定总的Chirp数量
    LVDS = zeros(1, fileSize);%%可以理解为它创建了一个1行fileSize(数据总量)列的表格
    %create column for each chirp
    LVDS = reshape(adcData, numADCSamples*numRX, numChirps);%%
LVDS = LVDS.';
else
numChirps = fileSize/2/numADCSamples/numRX;
LVDS = zeros(1, fileSize/2);
counter = 1;
for i=1:4:fileSize-1
LVDS(1,counter) = adcData(i) + sqrt(-1)*adcData(i+2); %%将数据转变成一个Lane通道中实部加虚部 
LVDS(1,counter+1) = adcData(i+1)+sqrt(-1)*adcData(i+3); %%的数据形式,并且按照noninterleaved 
counter = counter + 2;                                   %%的形式
end
LVDS = reshape(LVDS, numADCSamples*numRX, numChirps); %%%%将数据按照numChirps和 
                                                    numADCSample*numRX分离,
                                                    %%生成numChirps*numADCSample*numRX矩阵, 

LVDS = LVDS.';%%对矩阵进行装置,以chirp数量为行数,numRX*numADCSample数为列数,这一步的目的在于 
           %%将lane数据和chrip数分开,刚好使得每一行的往里数256列都属于同一个接收机接收的数据
end

在这段代码中,它主要实现的是1、判断需要捕获的数据是实数还是虚数(这个是由用户在mmWave Studio中自己选择的).2、确定捕获的数据个数,以及确定总的Chirp数量。对于实数来说,捕获的总数量=numSmaple(pre Chirp的采样点数)*numChirp(总的chirp数)*numRx(接收天线数)。对于虚数来说,捕获的总数量=numSmaple(pre Chirp的采样点数)*numChirp(总的chirp数)*numRx(接收天线数)*2。为什么乘以2是因为它一个Lane传输的数据量是2。

adcData = zeros(numRX,numChirps*numADCSamples);%%
for row = 1:numRX
for i = 1: numChirps
adcData(row, (i-1)*numADCSamples+1:i*numADCSamples) = LVDS(i, (row-1)*numADCSamples+1:row*numADCSamples);
end

 这段代码就在于将数据生成一个[numRx,numSample*numChirp]维度的表格,其中numRx是接收天线数,numSample是一个Chirp的采样点数,numChirp是总的采样点。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐