Matlab
parseFeitCSI.m
%{
Function which parse FeitCSI data.
usage: parseFeitCSI("path/to/FeitCSI/file")
returned data structure sample:
[
{
header: {
"csi_size":416,
"ftm_clock":144084200,
"num_rx":2,
"num_tx":1,
"num_subcarriers":52,
"rssi1":67,
"rssi2":68,
"source_mac":(0, 7, 14, 124, 232, 48),
"source_mac_string":"00:07:0e:7c:e8:30",
"rate_flags":49415,
"rate_format":"LEGACY_OFDM",
"channel_width":"20",
"mcs":7,
"antenna_a":true,
"antenna_b":true,
"ldpc":false,
"ss":1,
"beamforming":false
},
data: complex matrix[num_subcarriers, num_rx, num_tx]
},
{
header: ...,
data: ...
},
...
]
%}
function output = parseFeitCSI(fileName)
RATE_MCS_MOD_TYPE_POS = uint32(8);
RATE_MCS_MOD_TYPE_MSK = bitshift(uint32(0x7), RATE_MCS_MOD_TYPE_POS);
RATE_MCS_CCK_MSK = bitshift(uint32(0), RATE_MCS_MOD_TYPE_POS);
RATE_MCS_LEGACY_OFDM_MSK = bitshift(uint32(1), RATE_MCS_MOD_TYPE_POS);
RATE_MCS_HT_MSK = bitshift(uint32(2), RATE_MCS_MOD_TYPE_POS);
RATE_MCS_VHT_MSK = bitshift(uint32(3), RATE_MCS_MOD_TYPE_POS);
RATE_MCS_HE_MSK = bitshift(uint32(4), RATE_MCS_MOD_TYPE_POS);
RATE_MCS_EHT_MSK = bitshift(uint32(5), RATE_MCS_MOD_TYPE_POS);
RATE_MCS_CHAN_WIDTH_POS = uint32(11);
RATE_MCS_CHAN_WIDTH_MSK = bitshift(uint32(0x7), RATE_MCS_CHAN_WIDTH_POS);
RATE_MCS_CHAN_WIDTH_20_VAL = uint32(0);
RATE_MCS_CHAN_WIDTH_20 = bitshift(RATE_MCS_CHAN_WIDTH_20_VAL, RATE_MCS_CHAN_WIDTH_POS);
RATE_MCS_CHAN_WIDTH_40_VAL = uint32(1);
RATE_MCS_CHAN_WIDTH_40 = bitshift(RATE_MCS_CHAN_WIDTH_40_VAL, RATE_MCS_CHAN_WIDTH_POS);
RATE_MCS_CHAN_WIDTH_80_VAL = uint32(2);
RATE_MCS_CHAN_WIDTH_80 = bitshift(RATE_MCS_CHAN_WIDTH_80_VAL, RATE_MCS_CHAN_WIDTH_POS);
RATE_MCS_CHAN_WIDTH_160_VAL = uint32(3);
RATE_MCS_CHAN_WIDTH_160 = bitshift(RATE_MCS_CHAN_WIDTH_160_VAL, RATE_MCS_CHAN_WIDTH_POS);
RATE_MCS_CHAN_WIDTH_320_VAL = uint32(4);
RATE_MCS_CHAN_WIDTH_320 = bitshift(RATE_MCS_CHAN_WIDTH_320_VAL, RATE_MCS_CHAN_WIDTH_POS);
RATE_HT_MCS_CODE_MSK = uint32(7);
RATE_MCS_ANT_A_POS = uint32(14);
RATE_MCS_ANT_A_MSK = bitshift(uint32(1), RATE_MCS_ANT_A_POS);
RATE_MCS_ANT_B_POS = uint32(15);
RATE_MCS_ANT_B_MSK = bitshift(uint32(1), RATE_MCS_ANT_B_POS);
RATE_MCS_LDPC_POS = uint32(16);
RATE_MCS_LDPC_MSK = bitshift(uint32(1), RATE_MCS_LDPC_POS);
RATE_MCS_SS_POS = uint32(16);
RATE_MCS_SS_MSK = bitshift(uint32(1), RATE_MCS_SS_POS);
RATE_MCS_BEAMF_POS = uint32(16);
RATE_MCS_BEAMF_MSK = bitshift(uint32(1), RATE_MCS_BEAMF_POS);
function header = parseHeader(data)
header = {};
header.csi_size = typecast(data(1:4), 'uint32');
header.ftm_clock = typecast(data(9:12), 'uint32');
header.num_rx = data(47);
header.num_tx = data(48);
header.num_subcarriers = typecast(data(53:56), 'uint32');
header.rssi1 = typecast(data(61:64), 'uint32');
header.rssi2 = typecast(data(65:68), 'uint32');
header.source_mac = data(69:74);
header.source_mac_string = sprintf('%02x:%02x:%02x:%02x:%02x:%02x', header.source_mac);
header.rate_flags = typecast(data(93:96), 'uint32');
rate_format = bitand(header.rate_flags, RATE_MCS_MOD_TYPE_MSK);
if rate_format == RATE_MCS_CCK_MSK
rate_format = 'CCK';
elseif rate_format == RATE_MCS_LEGACY_OFDM_MSK
rate_format = 'LEGACY_OFDM';
elseif rate_format == RATE_MCS_VHT_MSK
rate_format = 'VHT';
elseif rate_format == RATE_MCS_HT_MSK
rate_format = 'HT';
elseif rate_format == RATE_MCS_HE_MSK
rate_format = 'HE';
elseif rate_format == RATE_MCS_EHT_MSK
rate_format = 'EHT';
else
rate_format = 'unknown';
end
header.rate_format = rate_format;
channel_width = bitand(header.rate_flags, RATE_MCS_CHAN_WIDTH_MSK);
if channel_width == RATE_MCS_CHAN_WIDTH_20
channel_width = '20';
elseif channel_width == RATE_MCS_CHAN_WIDTH_40
channel_width = '40';
elseif channel_width == RATE_MCS_CHAN_WIDTH_80
channel_width = '80';
elseif channel_width == RATE_MCS_CHAN_WIDTH_160
channel_width = '160';
elseif channel_width == RATE_MCS_CHAN_WIDTH_320
channel_width = '320';
else
channel_width = 'unknown';
end
header.channel_width = channel_width;
header.mcs = bitand(header.rate_flags, RATE_HT_MCS_CODE_MSK);
if bitand(header.rate_flags, RATE_MCS_ANT_A_MSK)
header.antenna_a = true;
else
header.antenna_a = false;
end
if bitand(header.rate_flags, RATE_MCS_ANT_B_MSK)
header.antenna_b = true;
else
header.antenna_b = false;
end
if bitand(header.rate_flags, RATE_MCS_LDPC_MSK)
header.ldpc = true;
else
header.ldpc = false;
end
if bitand(header.rate_flags, RATE_MCS_SS_MSK)
header.ss = 2;
else
header.ss = 1;
end
if bitand(header.rate_flags, RATE_MCS_BEAMF_MSK)
header.beamforming = true;
else
header.beamforming = false;
end
end
function csi_matrix = parseCsiData(data, header)
csi_matrix = zeros(header.num_subcarriers, header.num_rx, header.num_tx);
csi_matrix = complex(csi_matrix ,0);
pos = 1;
for j = 1:header.num_rx
for k = 1:header.num_tx
for n = 1:header.num_subcarriers
real = typecast(data(pos:pos + 1), 'int16');
imag = typecast(data(pos + 2:pos + 3), 'int16');
pos = pos + 4;
csi_matrix(n, j, k) = complex(real, imag);
end
end
end
end
f = fopen(fileName);
fileContent = uint8(fread(f));
step = 1;
index = 1;
while length(fileContent) > step
data = {};
data.header = parseHeader(fileContent(step:step + 271));
step = step + 272;
data.csi_matrix = parseCsiData(fileContent(step:step+data.header.csi_size - 1), data.header);
step = step + data.header.csi_size;
output(index ) = data;
index = index + 1;
end
end