新建
This commit is contained in:
commit
02f55955d5
72
Band_Mono_Parameter.m
Normal file
72
Band_Mono_Parameter.m
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
%%************************【频带干扰输出参数函数】****************************%%
|
||||||
|
%%=============================参数说明===================================%%
|
||||||
|
% J 检测出来的干扰点集合
|
||||||
|
% Power_mono 多音干扰功率集合
|
||||||
|
% f_mono 频带干扰频率集合
|
||||||
|
% Power_band 频带干扰功率
|
||||||
|
% f_wide 频带干扰带宽
|
||||||
|
% f_start频带起始频率
|
||||||
|
% f_end频带截止频率
|
||||||
|
% Num_band 频带干扰个数
|
||||||
|
% data 频域数据
|
||||||
|
% fs 采样频率
|
||||||
|
%%========================================================================%%
|
||||||
|
function [f_mono,Power_mono,Num_band,f_start,f_end,f_wide,Power_band] = Band_Mono_Parameter(data,J,fs,NFFT)
|
||||||
|
J = sort(J,'ascend')-1;
|
||||||
|
len_J = length(J);
|
||||||
|
f_start = [];
|
||||||
|
f_end = [];
|
||||||
|
c1=1;
|
||||||
|
mono_d = cell(0,0);
|
||||||
|
mono_s = cell(0,0);
|
||||||
|
mono = [];
|
||||||
|
f_d = [];
|
||||||
|
f_s = [];
|
||||||
|
power_m = [];
|
||||||
|
power_d = [];
|
||||||
|
power_s = [];
|
||||||
|
band = cell(0,0);
|
||||||
|
while c1 < len_J
|
||||||
|
c2 = 0;
|
||||||
|
while (c1 + c2 + 1 <= len_J && J(c1) + c2 + 1==J(c1 + c2 + 1))
|
||||||
|
c2 = c2 + 1;
|
||||||
|
end
|
||||||
|
if(c2 > 2)
|
||||||
|
band = [band;(J(c1:1:c1+c2))]; %%连续点超过3,记为频带干扰
|
||||||
|
end
|
||||||
|
if c2 == 2
|
||||||
|
mono_d = [mono_d;(J(c1:1:c1+c2))]; %%频谱扩散的单音
|
||||||
|
end
|
||||||
|
if c2 == 1
|
||||||
|
mono_s = [mono_s;(J(c1:1:c1+c2))];
|
||||||
|
end
|
||||||
|
if c2 == 0
|
||||||
|
mono = [mono,J(c1)];
|
||||||
|
end
|
||||||
|
c1 = c1 + c2 +1;
|
||||||
|
if c1 == len_J && J(len_J-1) + 1 ~= J(len_J)
|
||||||
|
mono = [mono,J(len_J)];
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for k = 1:numel(mono_d)
|
||||||
|
f_d(k) = mono_d{k}(2)*fs/NFFT/10^6;
|
||||||
|
power_d(k) = sum(abs(data(mono_d{k}+1)).^2)/NFFT^2;
|
||||||
|
end
|
||||||
|
for m = 1:numel(mono_s)
|
||||||
|
f_s(m) = 0.5*(mono_s{m}(1)+mono_s{m}(2))*fs/NFFT/10^6;
|
||||||
|
power_s(m) = sum(abs(data(mono_s{m}+1)).^2)/NFFT^2;
|
||||||
|
end
|
||||||
|
power_m = abs(data(mono+1)).^2/NFFT^2;
|
||||||
|
mono = mono*fs/NFFT/10^6;
|
||||||
|
power_mono1 = [power_m,power_d,power_s];
|
||||||
|
f_mono1 = [mono,f_d,f_s];
|
||||||
|
[f_mono,index] = sort(f_mono1,'ascend');
|
||||||
|
Power_mono = power_mono1(index);
|
||||||
|
for k = 1 : numel(band)
|
||||||
|
f_start(k) = band{k}(1)*fs/NFFT/10^6;
|
||||||
|
f_end(k) = band{k}(end)*fs/NFFT/10^6;
|
||||||
|
end
|
||||||
|
f_wide = sum(abs(f_start - f_end));
|
||||||
|
Power_band = 2*sum(abs(data(J+1)).^2)/NFFT^2;
|
||||||
|
Num_band = length(f_end);
|
||||||
|
end
|
74
Band_Multi_Parameter.m
Normal file
74
Band_Multi_Parameter.m
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
%%************************【频带干扰输出参数函数】****************************%%
|
||||||
|
%%=============================参数说明===================================%%
|
||||||
|
% J 检测出来的干扰点集合
|
||||||
|
% Power_multi 多音干扰功率集合
|
||||||
|
% f_multi 频带干扰频率集合
|
||||||
|
% Num_multi 多音干扰个数
|
||||||
|
% Power_band 频带干扰功率
|
||||||
|
% f_wide 频带干扰带宽
|
||||||
|
% f_start频带起始频率
|
||||||
|
% f_end频带截止频率
|
||||||
|
% Num_band 频带干扰个数
|
||||||
|
% data 频域数据
|
||||||
|
% fs 采样频率
|
||||||
|
%%========================================================================%%
|
||||||
|
function [Num_multi,f_multi,Power_multi,Num_band,f_start,f_end,f_wide,Power_band] = Band_Multi_Parameter(data,J,fs,NFFT)
|
||||||
|
J = sort(J,'ascend')-1;
|
||||||
|
len_J = length(J);
|
||||||
|
f_start = [];
|
||||||
|
f_end = [];
|
||||||
|
c1=1;
|
||||||
|
mono_d = cell(0,0);
|
||||||
|
mono_s = cell(0,0);
|
||||||
|
mono = [];
|
||||||
|
f_d = [];
|
||||||
|
f_s = [];
|
||||||
|
power_m = [];
|
||||||
|
power_d = [];
|
||||||
|
power_s = [];
|
||||||
|
band = cell(0,0);
|
||||||
|
while c1 < len_J
|
||||||
|
c2 = 0;
|
||||||
|
while (c1 + c2 + 1 <= len_J && J(c1) + c2 + 1==J(c1 + c2 + 1))
|
||||||
|
c2 = c2 + 1;
|
||||||
|
end
|
||||||
|
if(c2 > 2)
|
||||||
|
band = [band;(J(c1:1:c1+c2))]; %%连续点超过3,记为频带干扰
|
||||||
|
end
|
||||||
|
if c2 == 2
|
||||||
|
mono_d = [mono_d;(J(c1:1:c1+c2))]; %%频谱扩散的单音
|
||||||
|
end
|
||||||
|
if c2 == 1
|
||||||
|
mono_s = [mono_s;(J(c1:1:c1+c2))];
|
||||||
|
end
|
||||||
|
if c2 == 0
|
||||||
|
mono = [mono,J(c1)];
|
||||||
|
end
|
||||||
|
c1 = c1 + c2 +1;
|
||||||
|
if c1 == len_J && J(len_J-1) + 1 ~= J(len_J)
|
||||||
|
mono = [mono,J(len_J)];
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for k = 1:numel(mono_d)
|
||||||
|
f_d(k) = mono_d{k}(2)*fs/NFFT/10^6;
|
||||||
|
power_d(k) = sum(abs(data(mono_d{k}+1)).^2)/NFFT^2;
|
||||||
|
end
|
||||||
|
for m = 1:numel(mono_s)
|
||||||
|
f_s(m) = 0.5*(mono_s{m}(1)+mono_s{m}(2))*fs/NFFT/10^6;
|
||||||
|
power_s(m) = sum(abs(data(mono_s{m}+1)).^2)/NFFT^2;
|
||||||
|
end
|
||||||
|
power_m = abs(data(mono+1)).^2/NFFT^2;
|
||||||
|
mono = mono*fs/NFFT/10^6;
|
||||||
|
power_multi1 = [power_m,power_d,power_s];
|
||||||
|
f_multi1 = [mono,f_d,f_s];
|
||||||
|
[f_multi,index] = sort(f_multi1,'ascend');
|
||||||
|
Power_multi =power_multi1(index);
|
||||||
|
Num_multi = length(f_multi1);
|
||||||
|
for k = 1 : numel(band)
|
||||||
|
f_start(k) = band{k}(1)*fs/NFFT/10^6;
|
||||||
|
f_end(k) = band{k}(end)*fs/NFFT/10^6;
|
||||||
|
end
|
||||||
|
f_wide =sum( abs(f_start - f_end));
|
||||||
|
Power_band = 2*sum(abs(data(J+1)).^2)/NFFT^2;
|
||||||
|
Num_band = length(f_end);
|
||||||
|
end
|
37
Band_Parameter.m
Normal file
37
Band_Parameter.m
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
%%************************【频带干扰输出参数函数】****************************%%
|
||||||
|
%%=============================参数说明===================================%%
|
||||||
|
% J 检测出来的干扰点集合
|
||||||
|
% data 频域数据
|
||||||
|
% fs 采样频率
|
||||||
|
% NFFT FFT点数
|
||||||
|
% Power_band 频带干扰功率
|
||||||
|
% f_wide 频带干扰带宽
|
||||||
|
% f_start频带起始频率
|
||||||
|
% f_end频带截止频率
|
||||||
|
% Num_band 频带干扰个数
|
||||||
|
%%========================================================================%%
|
||||||
|
function [Num_band,f_start,f_end,f_wide,Power_band] = Band_Parameter(data,J,fs,NFFT)
|
||||||
|
J = sort(J,'ascend')-1;
|
||||||
|
len_J = length(J);
|
||||||
|
f_start = [];
|
||||||
|
f_end = [];
|
||||||
|
c1=1;
|
||||||
|
band = cell(0,0);
|
||||||
|
while c1 < len_J
|
||||||
|
c2 = 0;
|
||||||
|
while (c1 + c2 + 1 <= len_J && J(c1) + c2 + 1==J(c1 + c2 + 1))
|
||||||
|
c2 = c2 + 1;
|
||||||
|
end
|
||||||
|
if(c2 > 2)
|
||||||
|
band = [band;(J(c1:1:c1+c2))]; %%连续点超过3,记为频带干扰
|
||||||
|
end
|
||||||
|
c1 = c1 + c2 +1;
|
||||||
|
end
|
||||||
|
for k = 1 : numel(band)
|
||||||
|
f_start(k) = band{k}(1)*fs/NFFT/10^6;
|
||||||
|
f_end(k) = band{k}(end)*fs/NFFT/10^6;
|
||||||
|
Power_band(k) = 2*sum(abs(data(band{k}(1:end)+1)).^2)/NFFT^2;
|
||||||
|
end
|
||||||
|
f_wide = sum(abs(f_end - f_start));
|
||||||
|
Num_band = length(f_end);
|
||||||
|
end
|
84
Corrcoef_Calculate.m
Normal file
84
Corrcoef_Calculate.m
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
function RU_avai = Corrcoef_Calculate(staFeedback,Type, jam_data)
|
||||||
|
numUsers = length(staFeedback);
|
||||||
|
[Nst,numRx,numSTS] = size(staFeedback{1});
|
||||||
|
% combine_matrix = zeros(Nst,numRx*numUsers,numSTS);
|
||||||
|
% 将反馈矩阵按用户纵向拼接
|
||||||
|
combine_matrix = cell(1,numRx);
|
||||||
|
Nru = 4;
|
||||||
|
RU_avai = zeros(1,Nru);
|
||||||
|
for rxIdx = 1:numRx
|
||||||
|
combine_matrix{rxIdx} = zeros(Nst,numUsers,numSTS);
|
||||||
|
for userIdx = 1:numUsers
|
||||||
|
combine_matrix{rxIdx}(:,userIdx,:) = staFeedback{userIdx}(:,rxIdx,:);
|
||||||
|
end
|
||||||
|
|
||||||
|
ru1 = combine_matrix{rxIdx}(1:52,:,:);
|
||||||
|
ru2 = combine_matrix{rxIdx}(54:105,:,:);
|
||||||
|
ru3 = combine_matrix{rxIdx}(138:190,:,:);
|
||||||
|
ru4 = combine_matrix{rxIdx}(191:end,:,:);
|
||||||
|
RU_matrix = {ru1,ru2,ru3,ru4};
|
||||||
|
|
||||||
|
for ruIdx = 1:Nru
|
||||||
|
fprintf('第%d个RU:\n',ruIdx);
|
||||||
|
% 计算每个空间流在不同接收天线下的相关系数
|
||||||
|
Coefs = cell(1,numSTS);
|
||||||
|
num_corr = zeros(1,numSTS);
|
||||||
|
disp('每个空间流的信道相关系数矩阵为:');
|
||||||
|
for stsIdx = 1:numSTS
|
||||||
|
Coef = corrcoef(abs(RU_matrix{ruIdx}(:,:,stsIdx)));
|
||||||
|
Coef(logical(eye(size(Coef)))) = -1;
|
||||||
|
Coefs{stsIdx} = Coef;
|
||||||
|
disp(Coef);
|
||||||
|
num_corr(stsIdx) = sum(Coef>0.5,'all');
|
||||||
|
end
|
||||||
|
disp('相关系数大于0.5的天线为:');
|
||||||
|
disp(num_corr);
|
||||||
|
if sum(num_corr) == 0
|
||||||
|
RU_avai(ruIdx) = RU_avai(ruIdx)+1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
% figure();
|
||||||
|
% for rxIdx = 1:numRx
|
||||||
|
% for stsIdx = 1:numSTS
|
||||||
|
% for userIdx = 1:numUsers
|
||||||
|
% plot(abs(combine_matrix{rxIdx}(:,userIdx,stsIdx)));
|
||||||
|
% hold on;
|
||||||
|
% end
|
||||||
|
% end
|
||||||
|
% end
|
||||||
|
% hold off;
|
||||||
|
% pause(0.5);
|
||||||
|
% close;
|
||||||
|
|
||||||
|
|
||||||
|
% 判断频谱干扰对RU的影响
|
||||||
|
if strcmp(Type,'multi')
|
||||||
|
for Idx = 1:length(jam_data)
|
||||||
|
f_idx = jam_data{1}(Idx)/10*Nst;
|
||||||
|
if 1 < f_idx < 52
|
||||||
|
RU_avai(1) = RU_avai(1)-0.5;
|
||||||
|
elseif 54 < f_idx < 105
|
||||||
|
RU_avai(2) = RU_avai(2)-0.5;
|
||||||
|
elseif 138 < f_idx < 190
|
||||||
|
RU_avai(3) = RU_avai(3)-0.5;
|
||||||
|
elseif 191 < f_idx < Nst
|
||||||
|
RU_avai(4) = RU_avai(4)-0.5;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif strcmp(Type,'mono')
|
||||||
|
f_idx = jam_data/10*Nst;
|
||||||
|
if 1 < f_idx < 52
|
||||||
|
RU_avai(1) = RU_avai(1)-0.5;
|
||||||
|
elseif 54 < f_idx < 105
|
||||||
|
RU_avai(2) = RU_avai(2)-0.5;
|
||||||
|
elseif 138 < f_idx < 190
|
||||||
|
RU_avai(3) = RU_avai(3)-0.5;
|
||||||
|
elseif 191 < f_idx < Nst
|
||||||
|
RU_avai(4) = RU_avai(4)-0.5;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
fprintf('4个RU中可用的RU为:');
|
||||||
|
disp(RU_avai);
|
||||||
|
end
|
99
DataDecoding.m
Normal file
99
DataDecoding.m
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
function [] = DataDecoding(rx)
|
||||||
|
|
||||||
|
%% HE-Data Decoding
|
||||||
|
% The updated <matlab:edit('wlanHERecoveryConfig.m') wlanHERecoveryConfig>
|
||||||
|
% object for each user can then be used to recover the PSDU bits for each
|
||||||
|
% user in the HE-Data field.
|
||||||
|
|
||||||
|
cfgDataRec = trackingRecoveryConfig;
|
||||||
|
cfgDataRec.PilotTracking = pilotTracking;
|
||||||
|
|
||||||
|
fprintf('Decoding HE-Data...\n');
|
||||||
|
for iu = 1:numUsers
|
||||||
|
% Get recovery configuration object for each user
|
||||||
|
user = cfgUsers{iu};
|
||||||
|
if strcmp(pktFormat,'HE-MU')
|
||||||
|
fprintf(' Decoding User:%d, STAID:%d, RUSize:%d\n',iu,user.STAID,user.RUSize);
|
||||||
|
else
|
||||||
|
fprintf(' Decoding RUSize:%d\n',user.RUSize);
|
||||||
|
end
|
||||||
|
|
||||||
|
heInfo = wlanHEOFDMInfo('HE-Data',chanBW,user.GuardInterval,[user.RUSize user.RUIndex]);
|
||||||
|
|
||||||
|
% HE-LTF demodulation and channel estimation
|
||||||
|
rxHELTF = rx(pktOffset+(ind.HELTF(1):ind.HELTF(2)),:);
|
||||||
|
heltfDemod = wlanHEDemodulate(rxHELTF,'HE-LTF',chanBW,user.GuardInterval, ...
|
||||||
|
user.HELTFType,[user.RUSize user.RUIndex]);
|
||||||
|
[chanEst,pilotEst] = heLTFChannelEstimate(heltfDemod,user);
|
||||||
|
|
||||||
|
% Number of expected data OFDM symbols
|
||||||
|
symLen = heInfo.FFTLength+heInfo.CPLength;
|
||||||
|
numOFDMSym = (ind.HEData(2)-ind.HEData(1)+1)/symLen;
|
||||||
|
|
||||||
|
% HE-Data demodulation with pilot phase and timing tracking
|
||||||
|
% Account for extra samples when extracting data field from the packet
|
||||||
|
% for sample rate offset tracking. Extra samples may be required if the
|
||||||
|
% receiver clock is significantly faster than the transmitter.
|
||||||
|
maxSRO = 120; % Parts per million
|
||||||
|
Ne = ceil(numRxSamples*maxSRO*1e-6); % Number of extra samples
|
||||||
|
Ne = min(Ne,rxWaveLen-numRxSamples); % Limited to length of waveform
|
||||||
|
numRxSamplesProcess = numRxSamples+Ne;
|
||||||
|
rxData = rx(pktOffset+(ind.HEData(1):numRxSamplesProcess),:);
|
||||||
|
if user.RUSize==26
|
||||||
|
% Force CPE only tracking for 26-tone RU as algorithm susceptible
|
||||||
|
% to noise
|
||||||
|
cfgDataRec.PilotTracking = 'CPE';
|
||||||
|
else
|
||||||
|
cfgDataRec.PilotTracking = pilotTracking;
|
||||||
|
end
|
||||||
|
[demodSym,cpe,peg] = heTrackingOFDMDemodulate(rxData,chanEst,numOFDMSym,user,cfgDataRec);
|
||||||
|
|
||||||
|
% Estimate noise power in HE fields
|
||||||
|
demodPilotSym = demodSym(heInfo.PilotIndices,:,:);
|
||||||
|
nVarEst = heNoiseEstimate(demodPilotSym,pilotEst,user);
|
||||||
|
|
||||||
|
% Equalize
|
||||||
|
[eqSym,csi] = heEqualizeCombine(demodSym,chanEst,nVarEst,user);
|
||||||
|
|
||||||
|
% Discard pilot subcarriers
|
||||||
|
eqSymUser = eqSym(heInfo.DataIndices,:,:);
|
||||||
|
csiData = csi(heInfo.DataIndices,:);
|
||||||
|
|
||||||
|
% Demap and decode bits
|
||||||
|
rxPSDU = wlanHEDataBitRecover(eqSymUser,nVarEst,csiData,user,'LDPCDecodingMethod','layered-bp');
|
||||||
|
|
||||||
|
% Deaggregate the A-MPDU
|
||||||
|
[mpduList,~,status] = wlanAMPDUDeaggregate(rxPSDU,wlanHESUConfig);
|
||||||
|
if strcmp(status,'Success')
|
||||||
|
fprintf(' A-MPDU deaggregation successful \n');
|
||||||
|
else
|
||||||
|
fprintf(' A-MPDU deaggregation unsuccessful \n');
|
||||||
|
end
|
||||||
|
|
||||||
|
% Decode the list of MPDUs and check the FCS for each MPDU
|
||||||
|
for i = 1:numel(mpduList)
|
||||||
|
[~,~,status] = wlanMPDUDecode(mpduList{i},wlanHESUConfig,'DataFormat','octets');
|
||||||
|
if strcmp(status,'Success')
|
||||||
|
fprintf(' FCS pass for MPDU:%d\n',i);
|
||||||
|
else
|
||||||
|
fprintf(' FCS fail for MPDU:%d\n',i);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
% Plot equalized constellation of the recovered HE data symbols for all
|
||||||
|
% spatial streams per user
|
||||||
|
hePlotEQConstellation(eqSymUser,user,ConstellationDiagram,iu,numUsers);
|
||||||
|
|
||||||
|
% Measure EVM of HE-Data symbols
|
||||||
|
release(EVM);
|
||||||
|
EVM.ReferenceConstellation = wlanReferenceSymbols(user);
|
||||||
|
rmsEVM = EVM(eqSymUser(:));
|
||||||
|
fprintf(' HE-Data EVM:%2.2fdB\n\n',20*log10(rmsEVM/100));
|
||||||
|
|
||||||
|
% Plot EVM per symbol of the recovered HE data symbols
|
||||||
|
hePlotEVMPerSymbol(eqSymUser,user,EVMPerSymbol,iu,numUsers);
|
||||||
|
|
||||||
|
% Plot EVM per subcarrier of the recovered HE data symbols
|
||||||
|
hePlotEVMPerSubcarrier(eqSymUser,user,EVMPerSubcarrier,iu,numUsers);
|
||||||
|
end
|
||||||
|
end
|
81
DataGenerate.m
Normal file
81
DataGenerate.m
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
function txPSDU = DataGenerate(cfgUI,numPkt,SEED,arg,txPSDUByteUser)
|
||||||
|
%*********************************lql03.21修改*********************************
|
||||||
|
numUsers = cfgUI.numUsers;
|
||||||
|
DataType = cfgUI.DataType;
|
||||||
|
if isnumeric(arg)
|
||||||
|
if cfgUI.numUsers == 1
|
||||||
|
cfgHE = wlanHESUConfig;
|
||||||
|
else
|
||||||
|
cfgHE = wlanHEMUConfig(193);
|
||||||
|
end
|
||||||
|
psduLength = ones(1,numUsers)*arg;
|
||||||
|
else
|
||||||
|
if isfield(arg,'InterleavLen')
|
||||||
|
psduLength = arg.PacketSize;
|
||||||
|
else
|
||||||
|
cfgHE = arg;
|
||||||
|
psduLength = getPSDULength(cfgHE); % PSDU length in bytes
|
||||||
|
end
|
||||||
|
end
|
||||||
|
% psduLength = getPSDULength(cfgHE); % PSDU length in bytes
|
||||||
|
%*********************************lql03.21修改*********************************
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if numUsers==1
|
||||||
|
txPSDU = cell(1,1);
|
||||||
|
else
|
||||||
|
allocInfo = ruInfo(cfgHE);
|
||||||
|
txPSDU = cell(1,allocInfo.NumUsers);
|
||||||
|
end
|
||||||
|
% [len,width] = size(txPSDUByteUser(:,:,1));
|
||||||
|
|
||||||
|
if strcmp(cfgUI.DataType,'photo')
|
||||||
|
txPSDUBin = ones(length(txPSDUByteUser(:,1))*8,numUsers);
|
||||||
|
for userIdx = 1:numUsers
|
||||||
|
txPSDUBin(:,userIdx) = reshape(int2bit(txPSDUByteUser(:,userIdx),8),1,[]);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for i = 1:numPkt
|
||||||
|
if numUsers==1
|
||||||
|
rng(i+SEED);
|
||||||
|
switch DataType
|
||||||
|
case 'test'
|
||||||
|
txPSDU{1}(:,i) = randi([0 1],psduLength*8,1);
|
||||||
|
case 'text'
|
||||||
|
case 'photo'
|
||||||
|
% 将第i个包对应的内容赋值给第i个包 zjd3.26
|
||||||
|
if i*psduLength*8 <= length(txPSDUBin)
|
||||||
|
txPSDU{1}(:,i) = txPSDUBin((i-1)*psduLength*8+1:i*psduLength*8,:);
|
||||||
|
elseif i*psduLength*8 > length(txPSDUBin) && (i-1)*psduLength*8 < length(txPSDUBin)
|
||||||
|
padLength = psduLength*8-(length(txPSDUBin)-(i-1)*psduLength*8);
|
||||||
|
txPSDU{1}(:,i) = [txPSDUBin((i-1)*psduLength*8+1:length(txPSDUBin),:);randi([0 1],padLength,1)];
|
||||||
|
else
|
||||||
|
txPSDU{1}(:,i) = randi([0 1],psduLength*8,1);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
switch DataType
|
||||||
|
case 'test'
|
||||||
|
for ii = 1:allocInfo.NumUsers
|
||||||
|
rng(i+ii+SEED);
|
||||||
|
txPSDU{ii}(:,i) = randi([0 1],psduLength(ii)*8,1); % Generate random PSDU
|
||||||
|
end
|
||||||
|
case 'text'
|
||||||
|
case 'photo'
|
||||||
|
for ii = 1:allocInfo.NumUsers
|
||||||
|
% 将第i个包对应的内容赋值给第i个包 zjd3.26
|
||||||
|
if i*psduLength(ii)*8 <= length(txPSDUBin)
|
||||||
|
txPSDU{ii}(:,i) = txPSDUBin((i-1)*psduLength(ii)*8+1:i*psduLength(ii)*8,ii);
|
||||||
|
elseif (i*psduLength(ii)*8 > length(txPSDUBin)) && ((i-1)*psduLength(ii)*8 < length(txPSDUBin))
|
||||||
|
padLength = psduLength(ii)*8-(length(txPSDUBin)-(i-1)*psduLength(ii)*8); % 计算需要补多少随机数
|
||||||
|
txPSDU{ii}(:,i) = [txPSDUBin((i-1)*psduLength(ii)*8+1:length(txPSDUBin),ii);randi([0 1],padLength,1)];
|
||||||
|
else
|
||||||
|
txPSDU{ii}(:,i) = randi([0 1],psduLength(ii)*8,1);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
45
FCME.m
Normal file
45
FCME.m
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
%%************************【FCME检测算法函数】****************************%%
|
||||||
|
%%=============================参数说明===================================%%
|
||||||
|
% data 待检测的频域信号
|
||||||
|
% Pf 虚警概率
|
||||||
|
% J 检测出来的干扰点集合
|
||||||
|
%%========================================================================%%
|
||||||
|
function J = FCME(data,Pf)
|
||||||
|
T = sqrt(-1*(4/pi)*log(Pf)); %%门限因子
|
||||||
|
J = [];
|
||||||
|
L = length(data);
|
||||||
|
fi = [];
|
||||||
|
[y_sort,index] = sort(abs(data),'ascend'); %%按幅度值升序排列
|
||||||
|
%%求每个频点的幅值
|
||||||
|
for k = 1:L
|
||||||
|
fi(k)=abs(data(k));
|
||||||
|
end
|
||||||
|
%%%%初始化两个集合
|
||||||
|
J = index(round(L/10)+1:end); %%剩余有干扰集合
|
||||||
|
I = index(1:round(L/10)); %%无干扰集合\
|
||||||
|
S = mean(fi(I));
|
||||||
|
%%迭代求出干扰点集合
|
||||||
|
for m = 1:50 %%FCME迭代次数
|
||||||
|
length_J = length(J); %%J集合的长度
|
||||||
|
ii = 1;
|
||||||
|
jj = 1;
|
||||||
|
new_I = [];
|
||||||
|
new_J = [];
|
||||||
|
for j1 = 1:length_J
|
||||||
|
J1 = J(j1); %%J集合的索引
|
||||||
|
if fi(J1) < T*S %%如果小于门限,则移到I集合,从J集合剔除
|
||||||
|
new_I(ii) = J1;
|
||||||
|
ii = ii +1;
|
||||||
|
else %%如果大于于门限,则继续留在J集合
|
||||||
|
new_J(jj) = J1;
|
||||||
|
jj = jj + 1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if isempty(new_I) %%如果new_I为空,直接跳出
|
||||||
|
break;
|
||||||
|
end
|
||||||
|
J = new_J;
|
||||||
|
I = union(I,new_I);
|
||||||
|
S = mean(fi(I)); %%干扰频点
|
||||||
|
end
|
||||||
|
end
|
25
FCME_pro.m
Normal file
25
FCME_pro.m
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
%%***********************【改进FCME检测算法函数】*************************%%
|
||||||
|
%%=============================参数说明===================================%%
|
||||||
|
% data 待检测的频域信号
|
||||||
|
% Pf 虚警概率
|
||||||
|
% J 检测出来的干扰点集合
|
||||||
|
%%========================================================================%%
|
||||||
|
function J = FCME_pro(data_Freuq,Pf)
|
||||||
|
T = sqrt(-1*(4/pi)*log(Pf)); %%门限因子
|
||||||
|
th = 3.432; %%倍数关系
|
||||||
|
L = length(data_Freuq);
|
||||||
|
fi = [];
|
||||||
|
[y_sort,index] = sort(abs(data_Freuq),'ascend');
|
||||||
|
%%求每个频点的幅值
|
||||||
|
fi = abs(data_Freuq);
|
||||||
|
I = index(1:round(L/2)); %%无干扰集合
|
||||||
|
E = mean(fi(I));
|
||||||
|
Aaim = T*th*E; %%门限
|
||||||
|
J = [];
|
||||||
|
%%比较求得干扰集合
|
||||||
|
for mm = 1:L
|
||||||
|
if fi(mm) > Aaim
|
||||||
|
J = [J,mm];
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
24
HESU_gen.m
Normal file
24
HESU_gen.m
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
function byte = HESU_gen(byteIn,psduLength,userIdx)
|
||||||
|
PSDULength = psduLength(userIdx);
|
||||||
|
%Create a sequence of data bits and generate an HE SU waveform.
|
||||||
|
byteInLen=size(byteIn,1);
|
||||||
|
|
||||||
|
bits = zeros(8*PSDULength,1,'double');
|
||||||
|
%bits = randi([0 1],8*PSDULength,1,'int8');
|
||||||
|
|
||||||
|
if(byteInLen > 1)
|
||||||
|
if(byteInLen <= PSDULength)
|
||||||
|
bits(1:8*byteInLen) = int8(int2bit(byteIn,8));
|
||||||
|
else
|
||||||
|
bits = int8(int2bit(byteIn(1:PSDULength),8));
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
byte = int16(bit2int(bits,8));
|
||||||
|
|
||||||
|
%sr = wlanSampleRate(cfgHESU); % Sample rate
|
||||||
|
% TxWaveform = wlanWaveformGenerator(bits,cfgHESU);
|
||||||
|
%TxWaveform = wlanWaveformGenerator(bits,cfgHESU);
|
||||||
|
% TxWaveform = 0.25.*TxWaveform;
|
||||||
|
%Rx = TxWaveform;
|
||||||
|
end
|
71
JudgeTypeJam.m
Normal file
71
JudgeTypeJam.m
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
%%************************【判断干扰类型函数】****************************%%
|
||||||
|
%%=============================参数说明===================================%%
|
||||||
|
% J: 检测出来的干扰点集合
|
||||||
|
%Type: 干扰类型
|
||||||
|
%%========================================================================%%
|
||||||
|
function Type = JudgeTypeJam(J)
|
||||||
|
J = sort(J,'ascend');
|
||||||
|
len_J = length(J);
|
||||||
|
c1 = 1;
|
||||||
|
band = cell(0,0);
|
||||||
|
mono_d = cell(0,0);
|
||||||
|
mono = [];
|
||||||
|
if len_J == 0
|
||||||
|
Type = 'No jam';
|
||||||
|
elseif len_J <= 3 %&& len_J > 0 %% 检测点数小于3,判断是离散还是连续(单音或者多音)
|
||||||
|
if len_J == 1
|
||||||
|
Type = 'mono';
|
||||||
|
else
|
||||||
|
if len_J == 2
|
||||||
|
if J(2)-J(1) == 1
|
||||||
|
Type = 'mono';
|
||||||
|
else
|
||||||
|
Type = 'multi';
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if J(3) - J(1) == 2
|
||||||
|
Type = 'mono';
|
||||||
|
else
|
||||||
|
Type = 'multi';
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
while c1 < len_J
|
||||||
|
c2 = 0;
|
||||||
|
while (c1 + c2 + 1 <= len_J && J(c1) + c2 + 1== J(c1 + c2 + 1))
|
||||||
|
c2 = c2 + 1;
|
||||||
|
end
|
||||||
|
if(c2 > 2)
|
||||||
|
band = [band;(J(c1:1:c1+c2))]; %% 连续点超过3,记为频带干扰
|
||||||
|
end
|
||||||
|
if (c2 == 2 || c2 == 1)
|
||||||
|
mono_d = [mono_d;(J(c1:1:c1+c2))]; %% 频谱扩散的单音
|
||||||
|
end
|
||||||
|
if c2 == 0
|
||||||
|
mono = [mono,J(c1)];
|
||||||
|
end
|
||||||
|
c1 = c1 + c2 +1;
|
||||||
|
if c1 == len_J && J(len_J-1) + 1 ~= J(len_J)
|
||||||
|
mono = [mono,J(len_J)];
|
||||||
|
end
|
||||||
|
end
|
||||||
|
num_band = numel(band);
|
||||||
|
num_mono_d = numel(mono_d);
|
||||||
|
num_mono = length(mono);
|
||||||
|
num_multi = num_mono + num_mono_d;
|
||||||
|
if num_band ~= 0
|
||||||
|
if num_multi == 0
|
||||||
|
Type = 'band';
|
||||||
|
else
|
||||||
|
if num_multi >1
|
||||||
|
Type = 'band_multi';
|
||||||
|
else
|
||||||
|
Type = 'band_mono';
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
Type = 'multi';
|
||||||
|
end
|
||||||
|
end
|
||||||
|
%% end
|
26
MCS_sel.m
Normal file
26
MCS_sel.m
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
function [MCS, mcs_no] = MCS_sel(ModulationMode,CodeRate)
|
||||||
|
switch ModulationMode
|
||||||
|
case 'BPSK'
|
||||||
|
MCS = 0;
|
||||||
|
mcs_no = [2,2];
|
||||||
|
case 'QPSK'
|
||||||
|
if(CodeRate==1/2)
|
||||||
|
MCS = 1;mcs_no = [4,2]; end
|
||||||
|
if CodeRate==3/4
|
||||||
|
MCS = 2;mcs_no = [4,4]; end
|
||||||
|
case '16QAM'
|
||||||
|
if CodeRate==1/2
|
||||||
|
MCS = 3;mcs_no = [16,2]; end
|
||||||
|
if CodeRate==2/3
|
||||||
|
MCS = 4;mcs_no = [16,3]; end
|
||||||
|
if CodeRate==3/4
|
||||||
|
MCS = 4;mcs_no = [16,4]; end
|
||||||
|
case '64QAM'
|
||||||
|
if CodeRate==2/3
|
||||||
|
MCS = 5;mcs_no = [64,3]; end
|
||||||
|
if CodeRate==3/4
|
||||||
|
MCS = 6;mcs_no = [64,4]; end
|
||||||
|
if CodeRate==5/6
|
||||||
|
MCS = 7;mcs_no = [64,6]; end
|
||||||
|
end
|
||||||
|
end
|
9
MU_NDP.m
Normal file
9
MU_NDP.m
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
function txNDP = MU_NDP(cfgMUMIMO,guardInterval,ChannelBandwidth)
|
||||||
|
% 产生NDP
|
||||||
|
cfgNDP = wlanHESUConfig('APEPLength',0,'GuardInterval',guardInterval); % No data in an NDP
|
||||||
|
cfgNDP.ChannelBandwidth = ChannelBandwidth;
|
||||||
|
cfgNDP.NumTransmitAntennas = cfgMUMIMO.NumTransmitAntennas;
|
||||||
|
cfgNDP.NumSpaceTimeStreams = cfgMUMIMO.NumTransmitAntennas;
|
||||||
|
txNDP = wlanWaveformGenerator([],cfgNDP);
|
||||||
|
txNDP = [txNDP; zeros(50,size(txNDP,2))];
|
||||||
|
end
|
23
Mono_Parameter.m
Normal file
23
Mono_Parameter.m
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
%%************************【单音干扰输出参数函数】****************************%%
|
||||||
|
%%=============================参数说明===================================%%
|
||||||
|
% J 检测出来的干扰点集合
|
||||||
|
% data 频域数据
|
||||||
|
% fs 采样频率
|
||||||
|
% NFFT FFT点数
|
||||||
|
% Power_mono 单音干扰功率
|
||||||
|
% f_mono 单音干扰频率
|
||||||
|
%%========================================================================%%
|
||||||
|
function [f_mono,Power_mono] = Mono_Parameter(data,J,fs,NFFT)
|
||||||
|
J = sort(J,'ascend')-1;
|
||||||
|
len_J = length(J);
|
||||||
|
if len_J == 1
|
||||||
|
f_mono = J*fs/NFFT/10^6;
|
||||||
|
else
|
||||||
|
if len_J == 2
|
||||||
|
f_mono = 0.5*(J(1)+J(2))*fs/NFFT/10^6;
|
||||||
|
else
|
||||||
|
f_mono = J(2)*fs/NFFT/10^6;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
Power_mono =sum(abs(data(J+1)).^2)/NFFT^2;
|
||||||
|
end
|
57
Multi_Parameter.m
Normal file
57
Multi_Parameter.m
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
%%************************【多音干扰输出参数函数】****************************%%
|
||||||
|
%%=============================参数说明===================================%%
|
||||||
|
% J 检测出来的干扰点集合
|
||||||
|
% data 频域数据
|
||||||
|
% fs 采样频率
|
||||||
|
% NFFT FFT点数
|
||||||
|
% Power_multi 多音干扰功率集合
|
||||||
|
% f_multi 多音干扰频率集合
|
||||||
|
% Num_multi 多音干扰个数
|
||||||
|
%%========================================================================%%
|
||||||
|
function [Num_multi,f_multi,Power_multi] = Multi_Parameter(data,J,fs,NFFT)
|
||||||
|
J = sort(J,'ascend')-1;
|
||||||
|
len_J = length(J);
|
||||||
|
mono_d = cell(0,0);
|
||||||
|
mono_s = cell(0,0);
|
||||||
|
mono = [];
|
||||||
|
f_d = [];
|
||||||
|
f_s = [];
|
||||||
|
power_m = [];
|
||||||
|
power_d = [];
|
||||||
|
power_s = [];
|
||||||
|
c1 = 1;
|
||||||
|
while c1 < len_J
|
||||||
|
c2 = 0;
|
||||||
|
while (c1 + c2 + 1 <= len_J && J(c1) + c2 + 1==J(c1 + c2 + 1))
|
||||||
|
c2 = c2 + 1;
|
||||||
|
end
|
||||||
|
if c2 == 2
|
||||||
|
mono_d = [mono_d;(J(c1:1:c1+c2))]; %%频谱扩散的单音
|
||||||
|
end
|
||||||
|
if c2 == 1
|
||||||
|
mono_s = [mono_s;(J(c1:1:c1+c2))];
|
||||||
|
end
|
||||||
|
if c2 == 0
|
||||||
|
mono = [mono,J(c1)];
|
||||||
|
end
|
||||||
|
c1 = c1 + c2 +1;
|
||||||
|
if c1 == len_J && J(len_J-1) + 1 ~= J(len_J)
|
||||||
|
mono = [mono,J(len_J)];
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for k = 1:numel(mono_d)
|
||||||
|
f_d(k) = mono_d{k}(2)*fs/NFFT/10^6;
|
||||||
|
power_d(k) = sum(abs(data(mono_d{k}+1)).^2)/NFFT^2;
|
||||||
|
end
|
||||||
|
for m = 1:numel(mono_s)
|
||||||
|
f_s(m) = 0.5*(mono_s{m}(1)+mono_s{m}(2))*fs/NFFT/10^6;
|
||||||
|
power_s(m) = sum(abs(data(mono_s{m}+1)).^2)/NFFT^2;
|
||||||
|
end
|
||||||
|
power_m = abs(data(mono+1)).^2/NFFT^2;
|
||||||
|
mono = mono*fs/NFFT/10^6;
|
||||||
|
power_multi1 = [power_m,power_d,power_s];
|
||||||
|
f_multi1 = [mono,f_d,f_s];
|
||||||
|
[f_multi,index] = sort(f_multi1,'ascend');
|
||||||
|
Power_multi = power_multi1(index);
|
||||||
|
Num_multi = length(f_multi1);
|
||||||
|
end
|
125
PSD_plot.m
Normal file
125
PSD_plot.m
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
%% PSD Comparison of ADMM1, ADMM2, CFR and seperated OICF
|
||||||
|
%%% 经过SSPA后的性能比较
|
||||||
|
clc;clear;
|
||||||
|
%% System Parameter
|
||||||
|
% load system_parameter.mat K1 K2 deltaK2 B N1 N2 G L Finv1 Finv2 F1 F2
|
||||||
|
|
||||||
|
global X1 X2 x_mixed
|
||||||
|
% load Index4CCDF_Comparison.mat Index X1 X2 x_mixed
|
||||||
|
|
||||||
|
M = 4;
|
||||||
|
modu = [0 0 1 1; 0 1 0 1];
|
||||||
|
% load CCDF_Comparison_ADMM_P5_5000.mat zmixed_m_A1 zmixed_m_A2
|
||||||
|
% load CCDF_Comparison_OICF_P5_5000.mat zmixed_m_O
|
||||||
|
% load CCDF_Comparison_ICF_P5_5000.mat zmixed_m_R
|
||||||
|
% save PSD_comparison.mat...
|
||||||
|
% x_mixed zmixed_m_A1 zmixed_m_A2 zmixed_m_R zmixed_m_O
|
||||||
|
% load PSD_comparison.mat...
|
||||||
|
% x_mixed zmixed_m_A1 zmixed_m_A2 zmixed_m_R zmixed_m_O
|
||||||
|
load(['TXPackets\rx_for_User' num2str(1) '.mat'],'rx'); % 加载用户数据
|
||||||
|
x_mixed = rx;
|
||||||
|
symNum = length(x_mixed);
|
||||||
|
%% 取出PAPR最大的100个数据
|
||||||
|
[PAPR_dex,MeanPower_Orignal] = calculate_PAPR(x_mixed);
|
||||||
|
symNum = 1000;
|
||||||
|
for i = 1:symNum
|
||||||
|
[a(i),b(i)] = max(PAPR_dex);
|
||||||
|
PAPR_dex(b(i)) = 0;
|
||||||
|
end
|
||||||
|
% b = randi([1 5000],1,symNum);
|
||||||
|
x_mixed = x_mixed(:,b);[PAPR_dex,~] = calculate_PAPR(x_mixed);10*log10(mean(PAPR_dex));
|
||||||
|
% zmixed_m_A1=zmixed_m_A1(:,b);[PAPR_dex,~] = calculate_PAPR(zmixed_m_A1);10*log10(mean(PAPR_dex))
|
||||||
|
% zmixed_m_A2=zmixed_m_A2(:,b);[PAPR_dex,~] = calculate_PAPR(zmixed_m_A2);10*log10(mean(PAPR_dex))
|
||||||
|
% zmixed_m_R=zmixed_m_R(:,b); [PAPR_dex,~] = calculate_PAPR(zmixed_m_R);10*log10(mean(PAPR_dex))
|
||||||
|
% zmixed_m_O=zmixed_m_O(:,b); [PAPR_dex,~] = calculate_PAPR(zmixed_m_O);10*log10(mean(PAPR_dex))
|
||||||
|
%% SSPA Model
|
||||||
|
p = 3;IBO = 5;L=4;
|
||||||
|
% Original symbol with SSPA
|
||||||
|
x_origin_out = SSPA_model(p,IBO,x_mixed);
|
||||||
|
[~,MeanPower] = calculate_PAPR(x_origin_out);
|
||||||
|
x_origin_out = x_origin_out./sqrt(MeanPower*L);
|
||||||
|
% % ADMM1 symbol with SSPA
|
||||||
|
% x_A1_out = SSPA_model(p,IBO,zmixed_m_A1);
|
||||||
|
% [~,MeanPower] = calculate_PAPR(x_A1_out);
|
||||||
|
% x_A1_out = x_A1_out./sqrt(MeanPower*L);
|
||||||
|
% % ADMM2 symbol with SSPA
|
||||||
|
% x_A2_out = SSPA_model(p,IBO,zmixed_m_A2);
|
||||||
|
% [~,MeanPower] = calculate_PAPR(x_A2_out);
|
||||||
|
% x_A2_out = x_A2_out./sqrt(MeanPower*L);
|
||||||
|
% % CFR symbol with SSPA
|
||||||
|
% x_R_out = SSPA_model(p,IBO,zmixed_m_R);
|
||||||
|
% [~,MeanPower] = calculate_PAPR(x_R_out);
|
||||||
|
% x_R_out = x_R_out./sqrt(MeanPower*L);
|
||||||
|
% % OICF symbol with SSPA
|
||||||
|
% x_O_out = SSPA_model(p,IBO,zmixed_m_O);
|
||||||
|
% [~,MeanPower] = calculate_PAPR(x_O_out);
|
||||||
|
% x_O_out = x_O_out./sqrt(MeanPower*L);
|
||||||
|
%% PSD plot
|
||||||
|
mode = 1; % 1.周期图法:periodogram 2.周期图法加汉明窗 2.文氏窗法:pwelch
|
||||||
|
N = (512+36)*2;shift = -N/8;
|
||||||
|
|
||||||
|
[pxx,freq] = sprectrum(x_origin_out,mode,N);
|
||||||
|
pxx = circshift(pxx,shift);
|
||||||
|
plot(freq/pi,10*log10(pxx),'k','LineWidth',1);hold on;grid on
|
||||||
|
|
||||||
|
% [pxx,freq] = sprectrum(x_A1_out,mode,N);
|
||||||
|
% pxx = circshift(pxx,shift);
|
||||||
|
% plot(freq/pi,10*log10(pxx),'r','LineWidth',1);
|
||||||
|
%
|
||||||
|
% [pxx,freq] = sprectrum(x_A2_out,mode,N);
|
||||||
|
% pxx = circshift(pxx,shift);
|
||||||
|
% plot(freq/pi,10*log10(pxx),'b','LineWidth',1);
|
||||||
|
%
|
||||||
|
% [pxx,freq] = sprectrum(x_R_out,mode,N);
|
||||||
|
% pxx = circshift(pxx,shift);
|
||||||
|
% plot(freq/pi,10*log10(pxx),'.-r','LineWidth',1);
|
||||||
|
%
|
||||||
|
% [pxx,freq] = sprectrum(x_O_out,mode,N);
|
||||||
|
% pxx = circshift(pxx,shift);
|
||||||
|
% plot(freq/pi,10*log10(pxx),'g','LineWidth',1);
|
||||||
|
%
|
||||||
|
% xlim([-1 1]);ylim([-38 0.5])
|
||||||
|
% legend('Origin','ADMM1','ADMM2','CFR','OICF')
|
||||||
|
% xlabel('Normalized Frequency')
|
||||||
|
% ylabel('PSD (dB)')
|
||||||
|
|
||||||
|
%% APPENDIX FUNCTIONS
|
||||||
|
function [x_out] = SSPA_model(p,IBO,x)
|
||||||
|
[~,Mean_Power] = calculate_PAPR(x);
|
||||||
|
% PAPR_out_O = 10*log10(PAPR_dex);
|
||||||
|
C = sqrt(Mean_Power)*10^(IBO/20);
|
||||||
|
x_out = x./ (1+(abs(x)./C).^(2*p)).^(1/(2*p));
|
||||||
|
end
|
||||||
|
|
||||||
|
function [pxx,freq] = sprectrum(x,mode,N)
|
||||||
|
switch mode
|
||||||
|
case 1
|
||||||
|
[pxx,freq] = periodogram(x *sqrt(2*pi),[],N,'centered');
|
||||||
|
case 2
|
||||||
|
[pxx,freq] = periodogram(x *sqrt(2*pi),hamming(length(x(:,1))),N,'centered');
|
||||||
|
case 3
|
||||||
|
[pxx,freq] = pwelch(x *sqrt(2*pi),[],[],N,'centered');
|
||||||
|
end
|
||||||
|
pxx = mean(pxx,2);
|
||||||
|
end
|
||||||
|
|
||||||
|
function [PAPR_dex,Mean_Power] = calculate_PAPR(x)
|
||||||
|
% PAPR_dex 计算得到所有符号各自的PAPR
|
||||||
|
% Mean_Power 符号的平均功率
|
||||||
|
Signal_Power = abs(x).^2;
|
||||||
|
Peak_Power = max(Signal_Power,[],1); % norm(x,Inf)^2
|
||||||
|
Mean_Power = mean(Signal_Power,1); % norm(x,2)^2/(K*IF)
|
||||||
|
PAPR_dex = Peak_Power./Mean_Power;
|
||||||
|
end
|
||||||
|
|
||||||
|
function [EVM1,EVM2,EVM3,EVM_sum] = calculate_EVM(s1,s2,s3,symNum)
|
||||||
|
% 计算得到所有符号各自的EVM
|
||||||
|
global X1 X2_1 X2_2
|
||||||
|
EVM1=zeros(1,symNum);EVM2=zeros(1,symNum);EVM3=zeros(1,symNum);EVM_sum=zeros(1,symNum);
|
||||||
|
for i = 1:symNum
|
||||||
|
EVM1(i) = norm(X1(:,i)-s1(:,i),2)/norm(X1(:,i),2);
|
||||||
|
EVM2(i) = norm(X2_1(:,i)-s2(:,i),2)/norm(X2_1(:,i),2);
|
||||||
|
EVM3(i) = norm(X2_2(:,i)-s3(:,i),2)/norm(X2_2(:,i),2);
|
||||||
|
EVM_sum(i) = EVM1(i) + EVM2(i) + EVM3(i);
|
||||||
|
end
|
||||||
|
end
|
121
PassChannel.m
Normal file
121
PassChannel.m
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
|
||||||
|
load('TXPackets\transmit_data.mat','tx_data','cfgUI');
|
||||||
|
|
||||||
|
snr = 30;
|
||||||
|
|
||||||
|
if cfgUI.numUsers == 1
|
||||||
|
CommMode = 'HE-SU';
|
||||||
|
else
|
||||||
|
CommMode = 'HE-MU';
|
||||||
|
end
|
||||||
|
|
||||||
|
%*****************************************
|
||||||
|
% number of (real + virtual) users
|
||||||
|
RU_index = RU_alloc(cfgUI);
|
||||||
|
allocInfo = wlan.internal.heAllocationInfo(RU_index);
|
||||||
|
cfgUI.numUsers = allocInfo.NumUsers;
|
||||||
|
%*****************************************
|
||||||
|
|
||||||
|
rx_data = chanPass(tx_data,cfgUI,snr,CommMode);
|
||||||
|
for i =1:cfgUI.numUsers
|
||||||
|
matName = ['rx_for_User',num2str(i),'.mat'];
|
||||||
|
if cfgUI.numUsers == 1
|
||||||
|
rx = rx_data;
|
||||||
|
save(['TXPackets\',matName],'rx');
|
||||||
|
else
|
||||||
|
rx = rx_data{i};
|
||||||
|
save(['TXPackets\',matName],'rx');
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
%%
|
||||||
|
|
||||||
|
function rx = chanPass(txPad,cfgUI,snr,CommMode)
|
||||||
|
numTx = cfgUI.numTx;
|
||||||
|
numRx = cfgUI.numRx;
|
||||||
|
guardInterval = 0.8;% Guard interval in Microseconds
|
||||||
|
cfgNDP = wlanHESUConfig('APEPLength',0,'GuardInterval',guardInterval); % No data in an NDP
|
||||||
|
cfgNDP.ChannelBandwidth = cfgUI.ChannelBandwidth;
|
||||||
|
cfgNDP.NumTransmitAntennas = numTx;
|
||||||
|
cfgNDP.NumSpaceTimeStreams = numRx;
|
||||||
|
if strcmp(CommMode,'HE-SU')
|
||||||
|
% Create and configure the TGax channel
|
||||||
|
chanBW = cfgNDP.ChannelBandwidth;
|
||||||
|
tgaxChannel = wlanTGaxChannel;
|
||||||
|
tgaxChannel.DelayProfile = 'Model-B';
|
||||||
|
tgaxChannel.NumTransmitAntennas = cfgNDP.NumTransmitAntennas;
|
||||||
|
tgaxChannel.NumReceiveAntennas = numRx;
|
||||||
|
tgaxChannel.TransmitReceiveDistance = 5; % Distance in meters for NLOS
|
||||||
|
tgaxChannel.ChannelBandwidth = chanBW;
|
||||||
|
tgaxChannel.LargeScaleFadingEffect = 'None';
|
||||||
|
fs = wlanSampleRate(cfgNDP);
|
||||||
|
tgaxChannel.SampleRate = fs;
|
||||||
|
tgaxChannel.RandomStream = 'mt19937ar with seed';
|
||||||
|
tgaxChannel.Seed = 5;
|
||||||
|
% Get occupied subcarrier indices and OFDM parameters
|
||||||
|
ofdmInfo = wlanHEOFDMInfo('HE-Data',cfgNDP);
|
||||||
|
|
||||||
|
stream = RandStream('combRecursive','Seed',99);
|
||||||
|
% stream.Substream = snr;
|
||||||
|
RandStream.setGlobalStream(stream);
|
||||||
|
|
||||||
|
% Create an instance of the AWGN channel per SNR point simulated
|
||||||
|
awgnChannel = comm.AWGNChannel;
|
||||||
|
awgnChannel.NoiseMethod = 'Signal to noise ratio (SNR)';
|
||||||
|
awgnChannel.SignalPower = 1/tgaxChannel.NumReceiveAntennas;
|
||||||
|
% Account for noise energy in nulls so the SNR is defined per
|
||||||
|
% active subcarrier
|
||||||
|
awgnChannel.SNR = snr-10*log10(ofdmInfo.FFTLength/ofdmInfo.NumTones);
|
||||||
|
|
||||||
|
% Pass through a fading indoor TGax channel
|
||||||
|
% reset(tgaxChannel); % Reset channel for different realization
|
||||||
|
rx = tgaxChannel(txPad);
|
||||||
|
% Pass the waveform through AWGN channel
|
||||||
|
rx = awgnChannel(rx);
|
||||||
|
elseif strcmp(CommMode,'HE-MU')
|
||||||
|
tgaxBase = wlanTGaxChannel;
|
||||||
|
tgaxBase.DelayProfile = 'Model-D'; % Delay profile
|
||||||
|
tgaxBase.NumTransmitAntennas = cfgNDP.NumTransmitAntennas; % Number of transmit antennas
|
||||||
|
tgaxBase.NumReceiveAntennas = numRx; % Each user has two receive antennas
|
||||||
|
tgaxBase.TransmitReceiveDistance = 10; % Non-line of sight distance
|
||||||
|
tgaxBase.ChannelBandwidth = cfgNDP.ChannelBandwidth;
|
||||||
|
tgaxBase.SampleRate = wlanSampleRate(cfgNDP);
|
||||||
|
% Set a fixed seed for the channel
|
||||||
|
tgaxBase.RandomStream = 'mt19937ar with seed';
|
||||||
|
|
||||||
|
% Generate per-user channels
|
||||||
|
numUsers = cfgUI.numUsers; % Number of users simulated in this example
|
||||||
|
tgax = cell(1,numUsers);
|
||||||
|
for userIdx = 1:numUsers
|
||||||
|
% tgaxBase.Seed = randi(100);
|
||||||
|
tgaxBase.Seed = userIdx;
|
||||||
|
tgax{userIdx} = clone(tgaxBase);
|
||||||
|
tgax{userIdx}.UserIndex = userIdx; % Set unique user index
|
||||||
|
end
|
||||||
|
|
||||||
|
awgnChannel = comm.AWGNChannel;
|
||||||
|
awgnChannel.NoiseMethod = 'Signal to noise ratio (SNR)';
|
||||||
|
awgnChannel.SignalPower = 1/numRx;
|
||||||
|
% Account for noise energy in nulls so the SNR is defined per
|
||||||
|
% active subcarrier
|
||||||
|
awgnChannel.SNR = snr;
|
||||||
|
rxUsers = cell(1,numUsers);
|
||||||
|
% allocInfo = ruInfo(cfgNDP);
|
||||||
|
% 使数据经过信道
|
||||||
|
for userIdx = 1:numUsers
|
||||||
|
tgaxClone = cloneChannels(tgax);
|
||||||
|
rxUsers{userIdx} = tgaxClone{userIdx}(txPad);
|
||||||
|
rxUsers{userIdx} = awgnChannel(rxUsers{userIdx});
|
||||||
|
end
|
||||||
|
rx = rxUsers;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
function tgaxClone = cloneChannels(tgax)
|
||||||
|
% Clone the channels before running to ensure the same realization can be
|
||||||
|
% used in the next simulation
|
||||||
|
tgaxClone = cell(size(tgax));
|
||||||
|
numUsers = numel(tgax);
|
||||||
|
for i=1:numUsers
|
||||||
|
tgaxClone{i} = clone(tgax{i});
|
||||||
|
end
|
||||||
|
end
|
BIN
RU_Alloc.png
Normal file
BIN
RU_Alloc.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.1 KiB |
59
RU_alloc.m
Normal file
59
RU_alloc.m
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
function RU_index = RU_alloc(cfgUI)
|
||||||
|
if cfgUI.numUsers == 1
|
||||||
|
f_occupy = strcat(num2str((cfgUI.user1.f)'));
|
||||||
|
switch f_occupy.'
|
||||||
|
case '1111'
|
||||||
|
RU_index = 192;% 空分
|
||||||
|
case '1100'
|
||||||
|
RU_index = 96;% 106 频分
|
||||||
|
case '0011'
|
||||||
|
RU_index = 96;% 242 空分
|
||||||
|
case '1000'
|
||||||
|
RU_index = 112;% 52 频分
|
||||||
|
case '0100'
|
||||||
|
RU_index = 112;% 52 频分
|
||||||
|
case '0010'
|
||||||
|
RU_index = 112;% 52 频分
|
||||||
|
case '0001'
|
||||||
|
RU_index = 112;% 52 频分
|
||||||
|
otherwise
|
||||||
|
RU_index = 192;
|
||||||
|
end
|
||||||
|
RU_index = 192; % 为保证代码正常运行的权宜之计
|
||||||
|
elseif cfgUI.numUsers == 2
|
||||||
|
f_occupy = strcat(num2str((cfgUI.user1.f + cfgUI.user2.f)'));
|
||||||
|
switch f_occupy.'
|
||||||
|
case '2222'
|
||||||
|
RU_index = 193;% 242 空分
|
||||||
|
case '1111'
|
||||||
|
RU_index = 96;% 106 频分
|
||||||
|
case '2200'
|
||||||
|
RU_index = 100;% 242 空分
|
||||||
|
case '0022'
|
||||||
|
RU_index = 97;% 52 频分
|
||||||
|
case '1110'
|
||||||
|
RU_index = 24;% 52 频分
|
||||||
|
case '1101'
|
||||||
|
RU_index = 24;% 52 频分
|
||||||
|
case '0011'
|
||||||
|
RU_index = 24;% 52 频分
|
||||||
|
case '1011'
|
||||||
|
RU_index = 16;% 52 空分
|
||||||
|
case '0111'
|
||||||
|
RU_index = 16;% 52 频分
|
||||||
|
case '1100'
|
||||||
|
RU_index = 16;% 3用户,前106空分
|
||||||
|
case '1001'
|
||||||
|
RU_index = 112;% 52 频分
|
||||||
|
case '1010'
|
||||||
|
RU_index = 112;% 52 空分
|
||||||
|
case '0101'
|
||||||
|
RU_index = 112;% 52 频分
|
||||||
|
case '0110'
|
||||||
|
RU_index = 112;% 3用户,前106空分
|
||||||
|
otherwise
|
||||||
|
RU_index = 193;
|
||||||
|
end
|
||||||
|
RU_index = 193; % 为保证代码正常运行的权宜之计
|
||||||
|
end
|
||||||
|
end
|
45
RU_for_cfgUI.m
Normal file
45
RU_for_cfgUI.m
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
function cfgUI = RU_for_cfgUI(RU_avai,cfgUI)
|
||||||
|
mode = strrep(num2str(RU_avai),' ','');
|
||||||
|
if cfgUI.numUsers == 1
|
||||||
|
switch mode
|
||||||
|
case {'1111','1100','0011','1000','0100','0010','0001'}
|
||||||
|
cfgUI.user1.f = RU_avai;
|
||||||
|
case {'0111','1011'}
|
||||||
|
cfgUI.user1.f = [0,0,1,1];
|
||||||
|
case {'1101','1110'}
|
||||||
|
cfgUI.user1.f = [1,1,0,0];
|
||||||
|
case {'1001','1010'}
|
||||||
|
cfgUI.user1.f = [1,0,0,0];
|
||||||
|
case {'0110','0101'}
|
||||||
|
cfgUI.user1.f = [0,1,0,0];
|
||||||
|
end
|
||||||
|
elseif cfgUI.numUsers == 2
|
||||||
|
switch mode
|
||||||
|
case '1111'
|
||||||
|
cfgUI.user1.f = [1,1,1,1];
|
||||||
|
cfgUI.user2.f = [1,1,1,1];
|
||||||
|
case {'0111','1011','0011'}
|
||||||
|
cfgUI.user1.f = [0,0,1,1];
|
||||||
|
cfgUI.user2.f = [0,0,1,1];
|
||||||
|
case {'1101','1110','1100'}
|
||||||
|
cfgUI.user1.f = [1,1,0,0];
|
||||||
|
cfgUI.user2.f = [1,1,0,0];
|
||||||
|
case {'0001','0010','0100','1000'}
|
||||||
|
cfgUI.user1.f = RU_avai;
|
||||||
|
cfgUI.user2.f = RU_avai;
|
||||||
|
case '0101'
|
||||||
|
cfgUI.user1.f = [0,1,0,0];
|
||||||
|
cfgUI.user2.f = [0,0,0,1];
|
||||||
|
case '0110'
|
||||||
|
cfgUI.user1.f = [0,1,0,0];
|
||||||
|
cfgUI.user2.f = [0,0,1,0];
|
||||||
|
case '1001'
|
||||||
|
cfgUI.user1.f = [1,0,0,0];
|
||||||
|
cfgUI.user2.f = [0,0,0,1];
|
||||||
|
case '1010'
|
||||||
|
cfgUI.user1.f = [1,0,0,0];
|
||||||
|
cfgUI.user2.f = [0,0,1,0];
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
27
RX.m
Normal file
27
RX.m
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
clear;
|
||||||
|
close all;
|
||||||
|
clc;
|
||||||
|
%% LabVIEW界面参数配置1-接收模式-界面选择部分
|
||||||
|
cfgUI.DataType = 'photo'; % 'test''text''photo'
|
||||||
|
cfgUI.FeedbackMode = 'feedback'; % 'openloop','feedback';对应菜单栏的‘手动’和‘智能’
|
||||||
|
|
||||||
|
cfgUI.numTx = 2;
|
||||||
|
cfgUI.numRx = 1;
|
||||||
|
|
||||||
|
cfgUI.ChannelBandwidth = 'CBW20';
|
||||||
|
|
||||||
|
cfgUI.JamDetect = 'FCME_pro';%'AI'
|
||||||
|
cfgUI.syncSel = 'default';%'AI'
|
||||||
|
cfgUI.Estchan = 'default';%'AI-1''AI-2''AI-3'
|
||||||
|
cfgUI.decode = 'default';%'AI'
|
||||||
|
cfgUI.demod = 'default';%'AI'
|
||||||
|
cfgUI.semantic = 0; % 1 进行语义校验
|
||||||
|
userIdx = 1; % 解用户1 or 2的数据
|
||||||
|
|
||||||
|
cfgUI.numUsers = 2; % 用户数目
|
||||||
|
|
||||||
|
|
||||||
|
SEED = 1; % 收发约定的种子,用于生成比特计算BER
|
||||||
|
load(['TXPackets\rx_for_User' num2str(userIdx) '.mat'],'rx'); % 加载用户数据
|
||||||
|
|
||||||
|
[rxPSDU,bitErrorRate,pktFormat,pktOffset,eqSymPlot,Jam_pos,feedback_data,evm,errorMessage] = RX_function(rx,userIdx,cfgUI,SEED);
|
9
RX_CRC32.m
Normal file
9
RX_CRC32.m
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
function [rx,frmError] = RX_CRC32(dataPacketBits)
|
||||||
|
poly = [32,26,23,22,16,12,11,10,8,7,5,4,2,1,0];
|
||||||
|
crcdetector = comm.CRCDetector(...
|
||||||
|
'Polynomial', poly, ...
|
||||||
|
'InitialConditions', 1, ...
|
||||||
|
'DirectMethod', true, ...
|
||||||
|
'FinalXOR', 1);
|
||||||
|
[rx,frmError] = crcdetector(dataPacketBits);
|
||||||
|
end
|
61
RX_NDPCal.m
Normal file
61
RX_NDPCal.m
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
|
||||||
|
function [staFeedback,PDP,rmsDelay,DopplerShift,rssi_dbm,SNR] = RX_NDPCal(rx,cfgHE,ind,pktOffset,gain)
|
||||||
|
addpath(genpath('.\sounding'));
|
||||||
|
% ****手动调整NDP的尺寸
|
||||||
|
% rxNDP = txNDP(:,1:2);
|
||||||
|
% 计算引导矩阵
|
||||||
|
numTx = cfgHE.numTx;
|
||||||
|
cfgNDP = wlanHESUConfig('APEPLength',0,'GuardInterval',0.8); % No data in an NDP
|
||||||
|
cfgNDP.NumTransmitAntennas = numTx;%??
|
||||||
|
cfgNDP.NumSpaceTimeStreams = numTx;%??
|
||||||
|
txNDP = wlanWaveformGenerator([],cfgNDP);
|
||||||
|
len_NDP = length(txNDP);
|
||||||
|
% 加入PN序列,正交序列,重复三次左右
|
||||||
|
K = 255;
|
||||||
|
soundingSeqMod_1 = zadoffChuSeq(29,K);
|
||||||
|
soundingSeqMod_2 = zadoffChuSeq(47,K);
|
||||||
|
% Concatenate multiple sequences to sound the channel periodically.
|
||||||
|
numSeq = 10; % Number of transmitted sequences in a WSS period
|
||||||
|
soundingSeqMod = [soundingSeqMod_1, soundingSeqMod_2];
|
||||||
|
txSignal = repmat(soundingSeqMod,numSeq,1);
|
||||||
|
len_sd = length(txSignal);
|
||||||
|
% for userIdx = 1:numUsers
|
||||||
|
% NDP被接收端利用计算反馈信息
|
||||||
|
% Get the full-band beamforming feedback for a user
|
||||||
|
staFeedback = heUserBeamformingFeedback(rx,cfgNDP);
|
||||||
|
sounding_seq = rx(len_NDP+1:len_NDP+len_sd);
|
||||||
|
[PDP,rmsDelay,DopplerShift] = rxChannelSounding(sounding_seq,cfgHE,numSeq,K);
|
||||||
|
% end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
% RSSI
|
||||||
|
rxLSTF = rx(pktOffset+(ind.LSTF(1):ind.LSTF(2)),:)./(gain);
|
||||||
|
rssi_legancy = mean(abs(rxLSTF).^2);
|
||||||
|
rssi_legancy_dbm = 10*log10(rssi_legancy/1e-3);
|
||||||
|
|
||||||
|
rxHETF = rx(pktOffset+(ind.HESTF(1):ind.HELTF(2)),:)./(gain);
|
||||||
|
rssi = mean(abs(rxHETF).^2);
|
||||||
|
rssi_dbm = 10*log10(rssi/1e-3);
|
||||||
|
fprintf(' rssi_legancy: %f dBm\n rssi: %f dBm\n', rssi_legancy_dbm, rssi_dbm);
|
||||||
|
|
||||||
|
% SNR估计
|
||||||
|
LLTF = rx(ind.LLTF(1):ind.LLTF(2));
|
||||||
|
LLTF_length = length(LLTF);
|
||||||
|
LLTF1 = LLTF(1+LLTF_length/5:LLTF_length*3/5);
|
||||||
|
LLTF2 = LLTF(1+LLTF_length*3/5:end);
|
||||||
|
N = 64;
|
||||||
|
LLTF1_fft = ((abs(fftshift(fft(LLTF1)))).^2)/N;
|
||||||
|
LLTF2_fft = ((abs(fftshift(fft(LLTF2)))).^2)/N;
|
||||||
|
|
||||||
|
for i = 0:LLTF_length/160-1
|
||||||
|
power_signal = sum(LLTF1_fft(i*N+(7:32))) + sum(LLTF1_fft(i*N+(34:59))) + ...
|
||||||
|
sum(LLTF2_fft(i*N+(7:32))) + sum(LLTF2_fft(i*N+(34:59)));
|
||||||
|
power_noise = sum(LLTF1_fft(i*N+(1:6))) + sum(LLTF1_fft(i*N+(33))) + sum(LLTF1_fft(i*N+(end-4:end))) + ...
|
||||||
|
sum(LLTF2_fft(i*N+(1:6))) + sum(LLTF2_fft(i*N+(33))) + sum(LLTF2_fft(i*N+(end-4:end)));
|
||||||
|
end
|
||||||
|
SNR = 10*log10(power_signal/(power_noise*64/12));
|
||||||
|
fprintf(' SNR: %f dB\n', SNR);
|
||||||
|
|
||||||
|
rmpath(genpath('.\sounding'));
|
||||||
|
end
|
95
RX_function.m
Normal file
95
RX_function.m
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
function [rxPSDU,bitErrorRate,pktFormat,pktOffset,eqSymPlot,Jam_pos,feedback_data,evm,errorMessage] = RX_function(rx,userIdx,cfgUI,SEED)
|
||||||
|
|
||||||
|
cfgRx = wlanHERecoveryConfig;
|
||||||
|
cfgRx.ChannelBandwidth = cfgUI.ChannelBandwidth;
|
||||||
|
ind = wlanFieldIndices(cfgRx);
|
||||||
|
% 初始化,以防后续没有赋值--3.26
|
||||||
|
rxPSDU = [];
|
||||||
|
feedback_data = struct();
|
||||||
|
feedback_data.staFeedback = [];
|
||||||
|
feedback_data.PDP = [];
|
||||||
|
feedback_data.rmsDelay = 0;
|
||||||
|
feedback_data.DopplerShift = 0;
|
||||||
|
feedback_data.rssi = 0;
|
||||||
|
feedback_data.SNR = 0;
|
||||||
|
feedback_data.JamType = '';
|
||||||
|
feedback_data.JamData = [];
|
||||||
|
|
||||||
|
frameIdx = 1;
|
||||||
|
bitErrorRate = [];
|
||||||
|
eqSymPlot = [];
|
||||||
|
Jam_pos = [];
|
||||||
|
pktFormat = '';
|
||||||
|
pktOffset = 0;
|
||||||
|
evm = 0;
|
||||||
|
|
||||||
|
try
|
||||||
|
[Type,jam_data,Jam_pos] = SpectrumSense(rx,cfgUI); % 进行频谱检测
|
||||||
|
|
||||||
|
rxWaveLen = size(rx,1);
|
||||||
|
pktOffset = wlanPacketDetect(rx,cfgRx.ChannelBandwidth);% 检测是否有帧到来
|
||||||
|
% Adjust packet offset
|
||||||
|
if isempty(pktOffset) || (pktOffset + ind.LSIG(2) > rxWaveLen)
|
||||||
|
feedback_stat = 0;
|
||||||
|
else
|
||||||
|
feedback_stat = 1;
|
||||||
|
end
|
||||||
|
|
||||||
|
if feedback_stat==1
|
||||||
|
% 前端处理
|
||||||
|
[rx,pktOffset,gain] = rxFrontEnd(rx,pktOffset,ind,cfgRx);
|
||||||
|
% 判断接收数据的包格式
|
||||||
|
[cfgRx,~,ind] = pktFormatDetect(ind,pktOffset,rx,cfgRx);
|
||||||
|
%-------0324-----临时判断是nonHT还是HE-----------
|
||||||
|
if ~isfield(ind,'HEData')
|
||||||
|
pktFormat = 'non-HT';
|
||||||
|
fprintf('%s packet detected\n\n',pktFormat);
|
||||||
|
[rxPSDU,bitErrorRate,eqSymPlot]=heSUspecial(rx,cfgRx,userIdx,frameIdx,rxPSDU,cfgUI,SEED,bitErrorRate,eqSymPlot);
|
||||||
|
|
||||||
|
else
|
||||||
|
pktFormat = cfgRx.PacketFormat;
|
||||||
|
fprintf('%s packet detected\n\n',pktFormat);
|
||||||
|
% 解数据包
|
||||||
|
if strcmp(pktFormat,'HE-SU')
|
||||||
|
flag = isDataEmpty(rx,cfgUI); % 判断数据长度是否为0,为0则是NDP
|
||||||
|
if flag == 1 % 数据长度为0,说明是NDP
|
||||||
|
% *******计算NDP反馈的结果*******
|
||||||
|
pktFormat = 'NDP';
|
||||||
|
%--------------------------------
|
||||||
|
[staFeedback,PDP,rmsDelay,DopplerShift,rssi_dbm,SNR] = RX_NDPCal(rx,cfgUI,ind,pktOffset,gain);
|
||||||
|
% feedback_data = struct();
|
||||||
|
feedback_data.staFeedback = staFeedback;
|
||||||
|
feedback_data.PDP = PDP;
|
||||||
|
feedback_data.rmsDelay = rmsDelay;
|
||||||
|
feedback_data.DopplerShift = DopplerShift;
|
||||||
|
feedback_data.rssi = rssi_dbm;
|
||||||
|
feedback_data.SNR = SNR;
|
||||||
|
feedback_data.JamType = Type;
|
||||||
|
feedback_data.JamData = jam_data;
|
||||||
|
save(['TXPackets\NDPfeedback_for_User' num2str(userIdx) '.mat'],'feedback_data');
|
||||||
|
elseif flag == 0 % 数据长度不为零,说明是SU数据包
|
||||||
|
[rxPSDU,bitErrorRate,eqSymPlot] = heSURx(rx,cfgRx,userIdx,frameIdx,rxPSDU,cfgUI,SEED,bitErrorRate,eqSymPlot);
|
||||||
|
end
|
||||||
|
elseif strcmp(pktFormat,'HE-MU')
|
||||||
|
[rxPSDU,bitErrorRate,eqSymPlot,evm]=heMURx(rx,cfgRx,userIdx,frameIdx,rxPSDU,cfgUI,SEED,bitErrorRate,eqSymPlot);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
rxPSDU = int16(rxPSDU);
|
||||||
|
bitErrorRate = double(bitErrorRate);
|
||||||
|
pktOffset = double(pktOffset);
|
||||||
|
eqSymPlot = double(eqSymPlot);
|
||||||
|
Jam_pos = double(Jam_pos);
|
||||||
|
feedback_data.staFeedback = double(feedback_data.staFeedback);
|
||||||
|
feedback_data.PDP = double(feedback_data.PDP);
|
||||||
|
feedback_data.DopplerShift = double(feedback_data.DopplerShift);
|
||||||
|
feedback_data.rssi = double(feedback_data.rssi);
|
||||||
|
feedback_data.SNR = double(feedback_data.SNR);
|
||||||
|
feedback_data.JamData = double(feedback_data.JamData);
|
||||||
|
evm = double(evm);
|
||||||
|
|
||||||
|
errorMessage = '';
|
||||||
|
catch ErrorInfo
|
||||||
|
errorMessage = ErrorInfo.message;
|
||||||
|
end
|
||||||
|
end
|
25
Select_Detection.m
Normal file
25
Select_Detection.m
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
%%************************【选择检测算法函数】*****************************%%
|
||||||
|
%%=============================参数说明===================================%%
|
||||||
|
% data_Freuq 待检测的频域信号
|
||||||
|
% Pf 虚警概率(双门限代表低门限虚警概率)
|
||||||
|
% PfH 高门限虚警概率 (单门限时设置为零)
|
||||||
|
% operator 选择使用的检测算法
|
||||||
|
% JJ 检测出来的干扰点集合
|
||||||
|
%%========================================================================%%
|
||||||
|
function JJ = Select_Detection(data_Freuq,Pf,PfH,Num_step,operator)
|
||||||
|
if strcmp(operator,'CME')==1
|
||||||
|
JJ = CME(data_Freuq,Pf);
|
||||||
|
elseif strcmp(operator,'FCME')==1
|
||||||
|
JJ = FCME(data_Freuq,Pf);
|
||||||
|
elseif strcmp(operator,'FCME_hard')==1
|
||||||
|
JJ = FCME_hard(data_Freuq,Pf);
|
||||||
|
elseif strcmp(operator,'Double_Th_FCME')==1
|
||||||
|
JJ = Double_Th_FCME(data_Freuq,Pf,PfH);
|
||||||
|
elseif strcmp(operator,'FCME_pro')==1
|
||||||
|
JJ = FCME_pro(data_Freuq,Pf);
|
||||||
|
elseif strcmp(operator,'DiffFCME')==1
|
||||||
|
JJ = DiffFCME_B(data_Freuq,Pf,Num_step);
|
||||||
|
else
|
||||||
|
disp('Error,please enter the correct mode of operation!');
|
||||||
|
end
|
||||||
|
end
|
57
SpectrumSense.m
Normal file
57
SpectrumSense.m
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
function [Type,Jam_data,Jam_pos] = SpectrumSense(rx_format,cfgUI)
|
||||||
|
addpath(genpath('.\JamDetect'));
|
||||||
|
|
||||||
|
NFFT = 2048;
|
||||||
|
PfH = 0.0001;
|
||||||
|
Pf = 0.001;
|
||||||
|
fs = 20e6;
|
||||||
|
operator = cfgUI.JamDetect;
|
||||||
|
% 干扰检测
|
||||||
|
y = fft(rx_format(1:NFFT,:));
|
||||||
|
data_Freuq = y(1:NFFT/2,:);
|
||||||
|
J = Selecdt_Detection(data_Freuq,Pf,PfH,32,operator);
|
||||||
|
Type = JudgeTypeJam(J);
|
||||||
|
|
||||||
|
% struct jam_data;
|
||||||
|
jam_data.Num_multi = 0;
|
||||||
|
jam_data.f_multi = 0;
|
||||||
|
jam_data.Power_multi = [];
|
||||||
|
jam_data.Num_band = [];
|
||||||
|
jam_data.f_start = [];
|
||||||
|
jam_data.f_end = [];
|
||||||
|
jam_data.f_wide = [];
|
||||||
|
jam_data.Power_band = [];
|
||||||
|
|
||||||
|
if strcmp(Type,'multi')
|
||||||
|
[jam_data.Num_multi,jam_data.f_multi,jam_data.Power_multi] = Multi_Parameter(data_Freuq.',J,fs,NFFT);
|
||||||
|
elseif strcmp(Type,'mono')
|
||||||
|
[jam_data.f_multi,jam_data.Power_multi] = Mono_Parameter(data_Freuq.',J,fs,NFFT);
|
||||||
|
elseif strcmp(Type,'band')
|
||||||
|
[jam_data.Num_band,jam_data.f_start,jam_data.f_end,jam_data.f_wide,jam_data.Power_band] = Band_Parameter(data_Freuq.',J,fs,NFFT);
|
||||||
|
elseif strcmp(Type,'band_mono')
|
||||||
|
[jam_data.f_mono,jam_data.Power_mono,jam_data.Num_band,jam_data.f_start,jam_data.f_end,jam_data.f_wide,jam_data.Power_band] = Band_Mono_Parameter(data_Freuq.',J,fs,NFFT);
|
||||||
|
elseif strcmp(Type,'band_multi')
|
||||||
|
[jam_data.Num_multi,jam_data.f_multi,jam_data.Power_multi,jam_data.Num_band,jam_data.f_start,jam_data.f_end,jam_data.f_wide,jam_data.Power_band] = Band_Multi_Parameter(data_Freuq.',J,fs,NFFT);
|
||||||
|
else
|
||||||
|
disp('No jam!');
|
||||||
|
end
|
||||||
|
Jam_data = jam_data.f_multi;
|
||||||
|
dt=1/fs;
|
||||||
|
data_abs = 10*log(abs(data_Freuq(J)));
|
||||||
|
J_freuq=(J-1)/(dt*NFFT)/10^6; % 采样间隔
|
||||||
|
ssf=(0:NFFT/2-1)/(dt*NFFT); % 频率矢量
|
||||||
|
data_db=10*log(abs(data_Freuq));
|
||||||
|
Jam_pos = J_freuq*10^6;
|
||||||
|
% 取对数
|
||||||
|
%作图
|
||||||
|
% plot(ssf,data_db); % 做幅度频谱图
|
||||||
|
% grid on;
|
||||||
|
% hold on;
|
||||||
|
% stem(Jam_pos,data_abs,'m--','filled','MarkerSize',2)
|
||||||
|
% xlabel('frequency');
|
||||||
|
% ylabel('magnitude');
|
||||||
|
% hold off;
|
||||||
|
% pause(0.5);
|
||||||
|
% close;
|
||||||
|
rmpath(genpath('.\JamDetect'));
|
||||||
|
end
|
227
TX.m
Normal file
227
TX.m
Normal file
@ -0,0 +1,227 @@
|
|||||||
|
clear;
|
||||||
|
close all;
|
||||||
|
clc;
|
||||||
|
|
||||||
|
%% LabVIEW界面参数配置-发送模式-界面选择部分
|
||||||
|
|
||||||
|
cfgUI.ChannelBandwidth = 'CBW20'; % 下拉选择:'CBW20''CBW40''CBW80'
|
||||||
|
cfgUI.NTX2_enabled = 1; % 与第三方硬件连接
|
||||||
|
max_run_time = 60; %最大允许的等待时间
|
||||||
|
SEED = 1;
|
||||||
|
|
||||||
|
cfgUI.numUsers = 1; % 当前版本用户数量,1-2
|
||||||
|
cfgUI.DataType = 'test'; % 下拉选择:'test''text''photo'image.png
|
||||||
|
numPkt = 5; %时隙内包的数量,当前版本1~5
|
||||||
|
pktLength = 1001; % 包长度设定下拉选择(short,medium,long)对应几个数字1001,7007,12012,赋值给APEPLength
|
||||||
|
if strcmp(cfgUI.DataType,'photo')
|
||||||
|
txPSDUByte = imread('image.png');
|
||||||
|
I_gray = im2gray(txPSDUByte);
|
||||||
|
[len,width] = size(I_gray);
|
||||||
|
binary = dec2bin(I_gray(:),8);
|
||||||
|
bitstream = reshape(binary',1,[]);%将二进制数连接起来形成比特流
|
||||||
|
byte_array = reshape(bitstream',8,[])';%将比特流转换为字节流
|
||||||
|
txPSDUByte = bin2dec(byte_array);
|
||||||
|
% 包长度与包个数自适应判断 zjd3.26
|
||||||
|
if numPkt*pktLength >= length(txPSDUByte) % 如果当前包长度在5个包内能传输当前数据量
|
||||||
|
for pktNum = 1:numPkt % 判断当前包长度下最少用几个包传数据
|
||||||
|
if pktNum*pktLength >= length(txPSDUByte)
|
||||||
|
numPkt = pktNum;
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else % 当前包长度不能在5个包内能传输当前数据量,自动调整
|
||||||
|
if numPkt*7007 >= length(txPSDUByte)
|
||||||
|
for pktNum = 1:numPkt % 判断当前包长度下最少用几个包传数据
|
||||||
|
if pktNum*7007 >= length(txPSDUByte)
|
||||||
|
numPkt = pktNum;
|
||||||
|
pktLength = 7007;
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
for pktNum = 1:numPkt % 判断当前包长度下最少用几个包传数据
|
||||||
|
if pktNum*12012 >= length(txPSDUByte)
|
||||||
|
numPkt = pktNum;
|
||||||
|
pktLength = 12012;
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
txPSDUByteUser = zeros(len*width+3,cfgUI.numUsers); % 将图片分给两个用户
|
||||||
|
for i = 1:cfgUI.numUsers
|
||||||
|
byteLen = length(txPSDUByte);
|
||||||
|
byteLenBit = int2bit(byteLen,16);
|
||||||
|
Len1 = bit2int(byteLenBit(1:8),8);
|
||||||
|
Len2 = bit2int(byteLenBit(9:16),8);
|
||||||
|
txPSDUByteUser(1:len*width+2,i) = [Len1;Len2;txPSDUByte];
|
||||||
|
txPSDUByteUser(end,i) = mod(sum(txPSDUByteUser(:,i)),256);
|
||||||
|
end
|
||||||
|
txPSDUByteUser = uint8(txPSDUByteUser);
|
||||||
|
save('TXPackets\txPSDUByteUser.mat','txPSDUByteUser');
|
||||||
|
elseif strcmp(cfgUI.DataType,'text')
|
||||||
|
else
|
||||||
|
txPSDUByteUser = 0;
|
||||||
|
end
|
||||||
|
|
||||||
|
cfgUI.UserMode = 'SU'; % 使用模式下拉选择:'MU','SU',SU情况下只有单用户、可扩展40MHz、STBC等,MU模式可以对单用户进行资源分配(lxr)
|
||||||
|
cfgUI.FeedbackMode = 'openloop'; % 下拉选择: 'openloop','feedback',对应菜单栏的‘手动’和‘智能’
|
||||||
|
SoundingMode = 0; % 环境感知模式,作为一个按钮
|
||||||
|
|
||||||
|
cfgUI.numTx = 1; % 发射天线数,当前版本1~2
|
||||||
|
cfgUI.numRx = 1; % 接收天线数,当前版本1~2
|
||||||
|
|
||||||
|
cfgUI.AI.PAPR = 'PAPR'; % 下拉选择:'default','PAPR-Net'
|
||||||
|
cfgUI.PhySecur = 'default'; % 下拉选择:'无','CP随机化','信道密钥'
|
||||||
|
|
||||||
|
%----------------以下是可以手动配置的部分---------------------
|
||||||
|
%---资源矩阵部分
|
||||||
|
cfgUI.user1.s = 1;
|
||||||
|
cfgUI.user1.f = [1,1,1,1]; % 显示为4个方格,可用则为黑色为1,不可用则为白色为0
|
||||||
|
cfgUI.user1.t = ones(1,numPkt); % 显示为numPkt个方格,可用则为黑色为1,不可用则为白色为0
|
||||||
|
cfgUI.user1.p = 0.5; %
|
||||||
|
cfgUI.user2.s = 1;
|
||||||
|
cfgUI.user2.f = [1,1,1,1];
|
||||||
|
cfgUI.user2.t = ones(1,numPkt);
|
||||||
|
cfgUI.user2.p = 0.5;
|
||||||
|
%---波形参数部分---user1
|
||||||
|
cfgUI.user1.ChannelCode = 'LDPC'; % 下拉选择编码方式:BCC or LDPC
|
||||||
|
cfgUI.user1.CodeRate = 3/4; % 编码码率下拉选择:1/2 or 2/3 or 3/4 or 5/6
|
||||||
|
cfgUI.user1.CodeLengt = 1600; % 编码码长:200*8=1600,800
|
||||||
|
cfgUI.user1.InterWeaveMode = 'random'; % 交织方式下拉选择:random,horizontal
|
||||||
|
cfgUI.user1.InterWeaveDepth = 1024; % 交织深度:2048,1024
|
||||||
|
cfgUI.user1.ScrambleLength = 6; % 扰码长度:32
|
||||||
|
cfgUI.user1.CPLength = '1/4'; % CP长度下拉选择:1/16 or 1/8 or 1/4
|
||||||
|
cfgUI.user1.FFTSize = 256; % FFT尺寸:128 or 256 or 512
|
||||||
|
cfgUI.user1.NumSubcarrier = 242; % 子载波数:128 or 256 or 512
|
||||||
|
cfgUI.user1.ModulationMode = '16QAM'; % 调制方式下拉选择:4QAM or 8QAM or 16QAM or 32QAM or 64QAM
|
||||||
|
cfgUI.user1.MultiAntennaMode = 'STBC'; % 多天线方式下拉选择:'ZF-BF','MMSE-BF', SU模式下才能使用STBC'STBC'
|
||||||
|
cfgUI.user1.SpatialMapping = 'Hadamard'; % 空间映射方式下拉选择:'Direct','Hadamard','Fourier','Custom'----------zjd 3.21修改
|
||||||
|
cfgUI.user1.APEPlength = pktLength; % 包长度设定下拉选择(short,medium,long)对应几个数字1001,7007,12012
|
||||||
|
cfgUI.user1.pilotInterval = 5;
|
||||||
|
%---波形参数部分---user2
|
||||||
|
cfgUI.user2.ChannelCode = 'LDPC'; % 编码方式:BCC or LDPC
|
||||||
|
cfgUI.user2.CodeRate = 3/4; % 编码码率:1/2 or 2/3 or 3/4 or 5/6
|
||||||
|
cfgUI.user2.CodeLengt = 1600; % 编码码长:200*8=1600,800
|
||||||
|
cfgUI.user2.InterWeaveMode = 'random'; % 交织方式:random,horizontal
|
||||||
|
cfgUI.user2.InterWeaveDepth = 1024; % 交织深度:2048,1024
|
||||||
|
cfgUI.user2.ScrambleLength = 6; % 扰码长度:32
|
||||||
|
cfgUI.user2.CPLength = '1/4'; % CP长度:1/16 or 1/8 or 1/4
|
||||||
|
cfgUI.user2.FFTSize = 256; % FFT尺寸:128 or 256 or 512
|
||||||
|
cfgUI.user2.NumSubcarrier = 242; % 子载波数:128 or 256 or 512
|
||||||
|
cfgUI.user2.ModulationMode = '16QAM'; % 调制方式:4QAM or 8QAM or 16QAM or 32QAM or 64QAM
|
||||||
|
cfgUI.user2.MultiAntennaMode = 'ZF-BF'; % 多天线方式:'ZF-BF','MMSE-BF','STBC'
|
||||||
|
cfgUI.user2.SpatialMapping = 'Direct'; % 空间映射方式:'Direct','Hadamard','Fourier'
|
||||||
|
cfgUI.user2.APEPlength = pktLength; % 包长度设定
|
||||||
|
cfgUI.user2.pilotInterval = 5;
|
||||||
|
%% TX运行
|
||||||
|
if SoundingMode %%% 判断TX工作状态
|
||||||
|
tic;
|
||||||
|
feedback_stat = false;
|
||||||
|
while feedback_stat==false && toc < max_run_time % 没接收到反馈或者超过最大等待时间
|
||||||
|
txNDP = channelSounding(cfgUI); % 开始发送探测和NDP序列
|
||||||
|
tx_data = txNDP;
|
||||||
|
save('TXPackets\transmit_data.mat','tx_data','cfgUI');% 发送NDP
|
||||||
|
pause(1); % 暂停5s等待反馈
|
||||||
|
numUsers = cfgUI.numUsers;
|
||||||
|
feedback_data = struct(); % 初始化结构体
|
||||||
|
stat = zeros(1,numUsers);
|
||||||
|
for uid = 1:numUsers
|
||||||
|
filename = ['TXPackets/NDPfeedback_for_User' num2str(uid) '.mat'];
|
||||||
|
stat(uid) = 1;
|
||||||
|
if exist(filename,'file') ~= 2 % 待读取的反馈文件不存在
|
||||||
|
filename = ['TXPackets/NDPfeedback_Default_for_User' num2str(uid) '.mat']; % 读取默认的反馈文件
|
||||||
|
stat(uid) = 0; % 此时反馈参数为0
|
||||||
|
end
|
||||||
|
feedback_data = setfield(feedback_data,['user' num2str(uid)],loadfeedback(filename)); % 加载每个用户对应的反馈文件---需补充snr等(lxr)
|
||||||
|
end
|
||||||
|
feedback_stat = all(stat == 1); % 判断反馈状态
|
||||||
|
end
|
||||||
|
% 超时停止
|
||||||
|
if feedback_stat==false
|
||||||
|
error("Time Out !!!");
|
||||||
|
else
|
||||||
|
disp("feedback received");
|
||||||
|
end
|
||||||
|
|
||||||
|
elseif strcmp(cfgUI.FeedbackMode,'openloop')
|
||||||
|
while(1)
|
||||||
|
% 进入数据传输步骤
|
||||||
|
numUsers = cfgUI.numUsers; % 读取用户数
|
||||||
|
feedback_data = struct(); % 初始化结构体
|
||||||
|
for uid = 1:numUsers
|
||||||
|
filename = ['TXPackets/NDPfeedback_for_User' num2str(uid) '.mat'];
|
||||||
|
if exist(filename,'file') ~= 2 % 待读取的反馈文件不存在
|
||||||
|
filename = ['TXPackets/NDPfeedback_Default_for_User' num2str(uid) '.mat']; % 读取默认的反馈文件
|
||||||
|
end
|
||||||
|
feedback_data = setfield(feedback_data,['user' num2str(uid)],loadfeedback(filename)); % 加载每个用户对应的反馈文件
|
||||||
|
if eval(['isnan(sum(feedback_data.user' num2str(uid) '.staFeedback,"all")) || isempty(feedback_data.user' num2str(uid) '.staFeedback)']) % 判断staFeedback是否为空或NaN
|
||||||
|
filename = ['TXPackets/NDPfeedback_Default_for_User' num2str(uid) '.mat']; % 改为读取默认的反馈文件
|
||||||
|
feedback_data = setfield(feedback_data,['user' num2str(uid)],loadfeedback(filename));
|
||||||
|
end
|
||||||
|
end
|
||||||
|
[paraCal,tx_data,cfgUI,errorMessage] = TX_transmit(numPkt,SEED,cfgUI,feedback_data,txPSDUByteUser);
|
||||||
|
save('TXPackets\transmit_data.mat','tx_data','cfgUI');
|
||||||
|
if cfgUI.AI.PAPR == 'PAPR'
|
||||||
|
% PAPR DPD
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
elseif strcmp(cfgUI.FeedbackMode,'feedback')
|
||||||
|
|
||||||
|
while(1)
|
||||||
|
tic;
|
||||||
|
feedback_stat = false;
|
||||||
|
while feedback_stat==false && toc < max_run_time
|
||||||
|
txNDP = channelSounding(cfgUI); % 开始发送探测和NDP序列
|
||||||
|
tx_data = txNDP;
|
||||||
|
save('TXPackets\transmit_data.mat','tx_data','cfgUI');% 发送NDP
|
||||||
|
pause(0); % 暂停5s等待反馈
|
||||||
|
numUsers = cfgUI.numUsers; % 读取用户数
|
||||||
|
stat = zeros(1,numUsers); % 初始化stat参数
|
||||||
|
feedback_data = struct(); % 初始化结构体
|
||||||
|
for uid = 1:numUsers
|
||||||
|
filename = ['TXPackets/NDPfeedback_for_User' num2str(uid) '.mat'];
|
||||||
|
stat(uid) = 1;
|
||||||
|
if exist(filename,'file') ~= 2 % 待读取的反馈文件不存在
|
||||||
|
filename = ['TXPackets/NDPfeedback_Default_for_User' num2str(uid) '.mat']; % 读取默认的反馈文件
|
||||||
|
stat(uid) = 0; % 此时反馈参数为0
|
||||||
|
end
|
||||||
|
feedback_data = setfield(feedback_data,['user' num2str(uid)],loadfeedback(filename));
|
||||||
|
if eval(['isnan(sum(feedback_data.user' num2str(uid) '.staFeedback,"all")) || isempty(feedback_data.user' num2str(uid) '.staFeedback)']) % 判断staFeedback是否为空或NaN
|
||||||
|
filename = ['TXPackets/NDPfeedback_Default_for_User' num2str(uid) '.mat']; % 改为读取默认的反馈文件
|
||||||
|
feedback_data = setfield(feedback_data,['user' num2str(uid)],loadfeedback(filename));
|
||||||
|
end
|
||||||
|
end
|
||||||
|
feedback_stat = all(stat == 1); % 判断反馈状态
|
||||||
|
end
|
||||||
|
% 超时停止
|
||||||
|
if feedback_stat==false
|
||||||
|
error("Time Out !!!");
|
||||||
|
else
|
||||||
|
disp("feedback received");
|
||||||
|
end
|
||||||
|
%
|
||||||
|
|
||||||
|
% 进入参数配置步骤,数据传输步骤
|
||||||
|
ack_feedback_stat=true;
|
||||||
|
stat = 1;
|
||||||
|
while ack_feedback_stat==true && stat==1
|
||||||
|
load('TXPackets\feedback.mat');
|
||||||
|
feedback_data = feedback;
|
||||||
|
[paraCal,tx_data,cfgUI,errorMessage] = TX_transmit(numPkt,SEED,cfgUI,feedback_data,txPSDUByteUser);
|
||||||
|
save('TXPackets\transmit_data.mat','tx_data','cfgUI');
|
||||||
|
if cfgUI.AI.PAPR == 'PAPR'
|
||||||
|
% PAPR+DPD
|
||||||
|
end
|
||||||
|
pause(1); % 暂停 等待反馈
|
||||||
|
ACK_feedback = cell(1,numUsers);
|
||||||
|
for uid = 1:numUsers
|
||||||
|
load(['TXPackets\ACKfeedback_for_User' num2str(uid) '.mat'])
|
||||||
|
ACK_feedback{uid} = ACK;
|
||||||
|
end
|
||||||
|
% 显示空口波形参数,PAPR,以及AI算法的reward
|
||||||
|
show2LabVIEW(); %!!!
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
BIN
TXPackets/ACKfeedback_for_User1.mat
Normal file
BIN
TXPackets/ACKfeedback_for_User1.mat
Normal file
Binary file not shown.
BIN
TXPackets/ACKfeedback_for_User2.mat
Normal file
BIN
TXPackets/ACKfeedback_for_User2.mat
Normal file
Binary file not shown.
BIN
TXPackets/NDPfeedback_Default_for_User1.mat
Normal file
BIN
TXPackets/NDPfeedback_Default_for_User1.mat
Normal file
Binary file not shown.
BIN
TXPackets/NDPfeedback_Default_for_User2.mat
Normal file
BIN
TXPackets/NDPfeedback_Default_for_User2.mat
Normal file
Binary file not shown.
BIN
TXPackets/NDPfeedback_for_User1.mat
Normal file
BIN
TXPackets/NDPfeedback_for_User1.mat
Normal file
Binary file not shown.
BIN
TXPackets/NDPfeedback_for_User2.mat
Normal file
BIN
TXPackets/NDPfeedback_for_User2.mat
Normal file
Binary file not shown.
BIN
TXPackets/feedback.mat
Normal file
BIN
TXPackets/feedback.mat
Normal file
Binary file not shown.
BIN
TXPackets/rx_for_User1.mat
Normal file
BIN
TXPackets/rx_for_User1.mat
Normal file
Binary file not shown.
BIN
TXPackets/rx_for_User2.mat
Normal file
BIN
TXPackets/rx_for_User2.mat
Normal file
Binary file not shown.
BIN
TXPackets/rx_for_User3.mat
Normal file
BIN
TXPackets/rx_for_User3.mat
Normal file
Binary file not shown.
BIN
TXPackets/transmit_data.mat
Normal file
BIN
TXPackets/transmit_data.mat
Normal file
Binary file not shown.
BIN
TXPackets/txPSDUByteUser.mat
Normal file
BIN
TXPackets/txPSDUByteUser.mat
Normal file
Binary file not shown.
121
TX_SU.m
Normal file
121
TX_SU.m
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
function [txPad,cfgHE]=TX_SU(cfgHE,txPSDU)
|
||||||
|
|
||||||
|
if isfield(cfgHE,'InterleavLen')
|
||||||
|
tx = SU_Special(cfgHE,txPSDU);
|
||||||
|
% Add trailing zeros to allow for channel delay
|
||||||
|
txPad = [tx; zeros(30,1)];
|
||||||
|
else
|
||||||
|
|
||||||
|
% psduLength = getPSDULength(cfgHE); % PSDU length in bytes
|
||||||
|
% txPSDUcrc = TX_CRC32(txPSDU(1:(psduLength*8 - 32)));
|
||||||
|
txPSDUcrc = txPSDU;
|
||||||
|
tx = wlanWaveformGenerator(txPSDUcrc,cfgHE);
|
||||||
|
|
||||||
|
% Add trailing zeros to allow for channel delay
|
||||||
|
txPad = [tx; zeros(30,cfgHE.NumTransmitAntennas)];
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function crcData = TX_CRC32(dataPacketBits)
|
||||||
|
poly = [32,26,23,22,16,12,11,10,8,7,5,4,2,1,0];
|
||||||
|
crcGen32 = comm.CRCGenerator(...
|
||||||
|
'Polynomial', poly, ...
|
||||||
|
'InitialConditions', 1, ... % Initial states of the internal shift register 移位寄存器
|
||||||
|
'DirectMethod', true, ...
|
||||||
|
'FinalXOR', 1); % 打开 XOR操作
|
||||||
|
crcData = crcGen32(dataPacketBits);
|
||||||
|
end
|
||||||
|
%%
|
||||||
|
function tx = SU_Special(WaveformPara,txPSDU)
|
||||||
|
|
||||||
|
% tx_STF = STS_modulation(NumerologyNo); % STF
|
||||||
|
|
||||||
|
scrData = TX_CRC32_Scramble(txPSDU);
|
||||||
|
trellis = poly2trellis(7,[171 133]);
|
||||||
|
tx_encoded_bit = convenc(scrData,trellis,WaveformPara.puncpat);
|
||||||
|
tx_padded_bit = [tx_encoded_bit;zeros(WaveformPara.DataPadding,1)];
|
||||||
|
%---------------------------------------------
|
||||||
|
dataMod = qammod(tx_padded_bit,WaveformPara.Mod,'InputType','bit','UnitAveragePower',true);
|
||||||
|
WaveformPara.Power_sym = mean(abs(dataMod).^2);
|
||||||
|
dataMod = reshape(dataMod,WaveformPara.UsedSubcarrier,[]);
|
||||||
|
|
||||||
|
% 获取信道响应 %假设已知前一时刻的信号
|
||||||
|
% 生成信道响应
|
||||||
|
% N_carriers = WaveformPara.N_FFT;
|
||||||
|
% rng(2);
|
||||||
|
% channel_response=sqrt(1/2)*(randn(1,N_carriers)+1i*randn(1,N_carriers));
|
||||||
|
% % 窗的数目
|
||||||
|
% N_windows = 8;
|
||||||
|
% % 定义量化水平总数
|
||||||
|
% N_level = 10;
|
||||||
|
% % 最小CP值,外部条件,取决于最大延迟拓展,有最小CP值>最大延迟拓展
|
||||||
|
% min_len_CP = 30;
|
||||||
|
% % 测试函数
|
||||||
|
% CPset = Generate_CP(channel_response,N_windows,N_level,min_len_CP);
|
||||||
|
|
||||||
|
% 物理层加密
|
||||||
|
% [serialOFDMsym,WaveformPara.pilot,myFrameLen] = tx_FFTSymbolGen_PilotBlockPN(dataMod,WaveformPara,CPset); % 加CP的地方
|
||||||
|
[serialOFDMsym,WaveformPara.pilot] = tx_FFTSymbolGen_PilotBlockPN(dataMod,WaveformPara);
|
||||||
|
WaveformPara.Power_sig = mean(abs(serialOFDMsym).^2);
|
||||||
|
txdata = serialOFDMsym/sqrt(WaveformPara.Power_sig);
|
||||||
|
|
||||||
|
cfg = wlanNonHTConfig('SignalChannelBandwidth',true, ...
|
||||||
|
'BandwidthOperation','Static');
|
||||||
|
cfg.MCS = WaveformPara.MCS;
|
||||||
|
cfg.PSDULength = WaveformPara.PacketSize; %0-4095
|
||||||
|
% tx_STF = STS_modulation(NumerologyNo); % STF
|
||||||
|
FrameNo = WaveformPara.NumerologyNo;
|
||||||
|
tx_STF = wlanLSTF(cfg); % STF
|
||||||
|
tx_LTF = wlanLLTF(cfg); % LTF
|
||||||
|
[tx_SIG, tx_sigdata] = newLSIG(cfg,FrameNo);% SIG
|
||||||
|
|
||||||
|
tx = [tx_STF;tx_LTF;tx_SIG;serialOFDMsym;zeros(30,1)];
|
||||||
|
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function [serialOFDMsym,pilot] = tx_FFTSymbolGen_PilotBlockPN(dataModInMatrix,WaveformPara,SysParameters)
|
||||||
|
|
||||||
|
numOfdmSymbol = WaveformPara.FrameSymNum;
|
||||||
|
N_used = WaveformPara.UsedSubcarrier;
|
||||||
|
CP_Len = WaveformPara.CP_Len;
|
||||||
|
|
||||||
|
pnSequence = comm.PNSequence('Polynomial',[8 6 5 4 0], ...
|
||||||
|
'SamplesPerFrame',N_used,'InitialConditions',[0 0 0 0 0 0 0 1]);
|
||||||
|
|
||||||
|
% pilotPower = WaveformPara.Power_sym;
|
||||||
|
% pilot = generatePilot(pnSequence,pilotPower);
|
||||||
|
pilot = generatePilot(pnSequence,1);
|
||||||
|
|
||||||
|
m = WaveformPara.PilotNum-1;
|
||||||
|
dataModAddPilot = zeros(N_used,numOfdmSymbol);
|
||||||
|
for i = 1:m
|
||||||
|
dataModAddPilot(:,(i-1)*(WaveformPara.PilotInterval+1)+1:i*(WaveformPara.PilotInterval+1)) = ...
|
||||||
|
[pilot,dataModInMatrix(:,(i-1)*WaveformPara.PilotInterval+1:i*WaveformPara.PilotInterval)];
|
||||||
|
end
|
||||||
|
dataModAddPilot(:,m*(WaveformPara.PilotInterval+1)+1:end) = ...
|
||||||
|
[pilot,dataModInMatrix(:,m*WaveformPara.PilotInterval+1:end)];
|
||||||
|
|
||||||
|
dataModAddPilot_shift = [zeros(1,WaveformPara.FrameSymNum);...
|
||||||
|
dataModAddPilot(1:(N_used-1)/2,:);...
|
||||||
|
zeros(WaveformPara.NullSubcarrier,WaveformPara.FrameSymNum);...
|
||||||
|
dataModAddPilot(1+(N_used-1)/2:end,:)];
|
||||||
|
|
||||||
|
|
||||||
|
OFDMsym = ifft(dataModAddPilot_shift,[],1)*sqrt(WaveformPara.N_FFT)/sqrt(N_used)*sqrt(WaveformPara.N_FFT);
|
||||||
|
|
||||||
|
OFDMsymAddCP = [OFDMsym(WaveformPara.N_FFT-CP_Len+1:end,:);OFDMsym];
|
||||||
|
|
||||||
|
serialOFDMsym = reshape(OFDMsymAddCP,[],1);
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
function pilot = generatePilot(pnSequence,Power)
|
||||||
|
|
||||||
|
pilot = pnSequence();
|
||||||
|
|
||||||
|
bpskModulator = comm.BPSKModulator;
|
||||||
|
pilot = bpskModulator(pilot)*sqrt(Power);
|
||||||
|
end
|
124
TX_transmit.m
Normal file
124
TX_transmit.m
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
%*********************************lql03.21修改*********************************
|
||||||
|
function [paraCal,tx_data,cfgUI,errorMessage] = TX_transmit(numPkt,SEED,cfgUI,feedback_data,txPSDUfile)
|
||||||
|
% try
|
||||||
|
if strcmp(cfgUI.DataType,'photo')
|
||||||
|
pktLength = cfgUI.user1.APEPlength;
|
||||||
|
% 包长度与包个数自适应判断 zjd3.26
|
||||||
|
if numPkt*pktLength >= length(txPSDUfile(:,1)) % 如果当前包长度在5个包内能传输当前数据量
|
||||||
|
for pktNum = 1:numPkt % 判断当前包长度下最少用几个包传数据
|
||||||
|
if pktNum*pktLength >= length(txPSDUfile(:,1))
|
||||||
|
numPkt = pktNum;
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else % 当前包长度不能在5个包内能传输当前数据量,自动调整
|
||||||
|
if numPkt*7007 >= length(txPSDUfile(:,1))
|
||||||
|
for pktNum = 1:numPkt % 判断当前包长度下最少用几个包传数据
|
||||||
|
if pktNum*7007 >= length(txPSDUfile(:,1))
|
||||||
|
numPkt = pktNum;
|
||||||
|
pktLength = 7007;
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
for pktNum = 1:numPkt % 判断当前包长度下最少用几个包传数据
|
||||||
|
if pktNum*12012 >= length(txPSDUfile(:,1))
|
||||||
|
numPkt = pktNum;
|
||||||
|
pktLength = 12012;
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
% 配置计算后的参数
|
||||||
|
cfgUI.user1.APEPlength = pktLength;
|
||||||
|
cfgUI.user2.APEPlength = pktLength;
|
||||||
|
cfgUI.user1.t = ones(1,numPkt);
|
||||||
|
cfgUI.user2.t = ones(1,numPkt);
|
||||||
|
end
|
||||||
|
if strcmp(cfgUI.FeedbackMode,'feedback')
|
||||||
|
[cfgHE,RU_index,cfgUI] = parameter_fromAlgorithm(cfgUI,feedback_data);% 根据反馈数据配置RU
|
||||||
|
else
|
||||||
|
[cfgHE,RU_index,cfgUI] = parameter_fromUI(cfgUI); % 参数与RU配置
|
||||||
|
end
|
||||||
|
%*********************************lql03.21修改*********************************
|
||||||
|
showResourceMatrix(cfgHE,cfgUI,RU_index); % 展示资源分配情况
|
||||||
|
txPSDU = DataGenerate(cfgUI,numPkt,SEED,cfgHE,txPSDUfile);
|
||||||
|
% for i = 1:length(txPSDU)
|
||||||
|
% txPSDU{i} = HESU_gen(txPSDU,cfgUI.ChannelBandwidth,cfgHE.User{1}.MCS);
|
||||||
|
% end
|
||||||
|
|
||||||
|
|
||||||
|
tx_data = [];
|
||||||
|
% HE-SU
|
||||||
|
if strcmp(cfgUI.UserMode,'SU')
|
||||||
|
txPSDU = txPSDU{1};
|
||||||
|
% --------------------------------zjd0323修改-----------------------
|
||||||
|
for pnum = 1 : numPkt
|
||||||
|
[txPad,cfgHE]=TX_SU(cfgHE,txPSDU(:,pnum));
|
||||||
|
tx_awgn = wgn(600,cfgHE.NumTransmitAntennas,-20,'complex');
|
||||||
|
tx_data = [tx_data;txPad;tx_awgn]; % 帧间补零
|
||||||
|
end
|
||||||
|
tx_data = [tx_awgn(1:50,:);tx_data]; % 帧头补零
|
||||||
|
|
||||||
|
elseif strcmp(cfgUI.UserMode,'MU')
|
||||||
|
% HE-MU
|
||||||
|
if strcmp(cfgUI.FeedbackMode,'feedback')
|
||||||
|
|
||||||
|
%*********************************lql03.21修改*********************************
|
||||||
|
% 补充虚拟用户的feedback_data
|
||||||
|
for nuser = 1 : length(cfgHE.User)
|
||||||
|
STAID = cfgHE.User{nuser}.STAID;
|
||||||
|
if STAID == 0
|
||||||
|
eval(['Feedback_data.user' num2str(nuser) '= feedback_data.user2']);
|
||||||
|
else
|
||||||
|
eval(['Feedback_data.user' num2str(nuser) '= feedback_data.user' num2str(STAID)]);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
staFeedback = cell(1,length(cfgHE.User));
|
||||||
|
for userIdx = 1:length(cfgHE.User)
|
||||||
|
eval(['staFeedback{userIdx} = Feedback_data.user' num2str(userIdx) '.staFeedback;']);
|
||||||
|
end
|
||||||
|
%*********************************lql03.21修改*********************************
|
||||||
|
cfgNDP = wlanHESUConfig('APEPLength',0,'GuardInterval',0.8); % No data in an NDP
|
||||||
|
cfgNDP.NumTransmitAntennas = cfgHE.NumTransmitAntennas;%??
|
||||||
|
cfgNDP.NumSpaceTimeStreams = 1;%??
|
||||||
|
% For each RU calculate the steering matrix to apply
|
||||||
|
for ruIdx = 1:numel(cfgHE.RU)
|
||||||
|
% Calculate the steering matrix to apply to the RU given the feedback
|
||||||
|
steeringMatrix = heMUCalculateSteeringMatrix(staFeedback,cfgHE,cfgNDP,ruIdx);
|
||||||
|
% Apply the steering matrix to each RU
|
||||||
|
cfgHE.RU{ruIdx}.SpatialMapping = 'Custom';
|
||||||
|
cfgHE.RU{ruIdx}.SpatialMappingMatrix = steeringMatrix;
|
||||||
|
end
|
||||||
|
elseif strcmp(cfgUI.FeedbackMode,'openloop')
|
||||||
|
for ruIdx = 1:numel(cfgHE.RU)
|
||||||
|
% Apply the steering matrix to each RU
|
||||||
|
% cfgHE.RU{ruIdx}.SpatialMapping = cfgUI.user1.SpatialMapping;%% --???
|
||||||
|
cfgHE.RU{ruIdx}.SpatialMapping = 'Hadamard';
|
||||||
|
end
|
||||||
|
end
|
||||||
|
% Generate waveform with idle period
|
||||||
|
for pnum = 1 : numPkt
|
||||||
|
userString = '{';
|
||||||
|
for nuser = 1 : length(cfgHE.User)
|
||||||
|
userString = [userString 'txPSDU{' num2str(nuser) '}(:,pnum),'];
|
||||||
|
end
|
||||||
|
txPSDUtmp = eval([userString(1:(end-1)) '}']); %%------------需添加CRC
|
||||||
|
tx = wlanWaveformGenerator(txPSDUtmp,cfgHE);
|
||||||
|
tx_awgn = wgn(600,cfgHE.NumTransmitAntennas,-20,'complex');
|
||||||
|
% awgn(zeros(600,cfgHE.NumTransmitAntennas),20,'linear',1,'all');
|
||||||
|
tx_data = [tx_data;tx;tx_awgn]; % 帧间补零
|
||||||
|
end
|
||||||
|
tx_data = [tx_awgn(1:50,:);tx_data]; % 帧头补零
|
||||||
|
% tx_data = awgn(tx_data,30,mean(abs(tx_data(1:1000)).^2)); % 添加噪声
|
||||||
|
end
|
||||||
|
paraCal = calculate_PAPR(tx_data(1500:2500,:));
|
||||||
|
errorMessage = '';
|
||||||
|
% catch ErrorInfo
|
||||||
|
% paraCal = 0;
|
||||||
|
% tx_data = [];
|
||||||
|
% cfgUI = struct();
|
||||||
|
% errorMessage = ErrorInfo.message;
|
||||||
|
% end
|
||||||
|
end
|
28
WaveAdp/ChanStat.m
Normal file
28
WaveAdp/ChanStat.m
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
function ChanPara = ChanStat(SNR, tau_d, velocity, Ts, FreqCarrier, TimeStamp)
|
||||||
|
A_dB = -15;norm_flag = 1;c = 3e8;
|
||||||
|
ChanPara.PDP = exp_PDP(tau_d,Ts,A_dB,norm_flag);
|
||||||
|
ChanPara.delay = ones(1,length(ChanPara.PDP))*Ts;
|
||||||
|
ChanPara.rmsdelay = tau_d;
|
||||||
|
ChanPara.doppler = 'Jakes';
|
||||||
|
ChanPara.Velocity = velocity;
|
||||||
|
ChanPara.epsilon = 0;
|
||||||
|
ChanPara.SNR = SNR;
|
||||||
|
ChanPara.FreqCarrier = FreqCarrier;
|
||||||
|
ChanPara.MaximumDopplerShift = FreqCarrier/c * velocity/3600 *1000;
|
||||||
|
ChanPara.SampleFs = 1/Ts;
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function PDP = exp_PDP(tau_d,Ts,A_dB,norm_flag)
|
||||||
|
if nargin<4, norm_flag=1; end % normalizes
|
||||||
|
if nargin<3, A_dB=-20; end % 20dB below
|
||||||
|
sigma_tau = tau_d; A = 10^(A_dB/10);
|
||||||
|
lmax=ceil(-tau_d*log(A)/Ts); % get max. path index (2.8)/Ts
|
||||||
|
% Computes normalization factor for power normalization
|
||||||
|
if norm_flag
|
||||||
|
p0=(1-exp(-Ts/sigma_tau))/(1-exp(-(lmax+1)*Ts/sigma_tau)); % (2.10)
|
||||||
|
else p0=1/sigma_tau;
|
||||||
|
end
|
||||||
|
% Exponential PDP
|
||||||
|
l=0:lmax; PDP = p0*exp(-l*Ts/sigma_tau); % (2.11)
|
||||||
|
end
|
61
WaveAdp/ExecutedMAIN0701.m
Normal file
61
WaveAdp/ExecutedMAIN0701.m
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
%%
|
||||||
|
function [BER,PER,SyncErr] = ExecutedMAIN0701(PacketSize, NumerologySel, MCS_no, ChanPara, FreqCarrier, FrameNo, seed_set)
|
||||||
|
[SysParameters,WaveformPara] = WaveformNumerologyCal(PacketSize,NumerologySel,MCS_no);
|
||||||
|
%% TX
|
||||||
|
rng(seed_set(1),'twister');
|
||||||
|
dataPacketBits = randi([0 1],WaveformPara.Payload,1);
|
||||||
|
scrData = TX_CRC32_Scramble(dataPacketBits);
|
||||||
|
trellis = poly2trellis(7,[171 133]);
|
||||||
|
tx_encoded_bit = convenc(scrData,trellis,WaveformPara.puncpat);
|
||||||
|
tx_padded_bit = [tx_encoded_bit;zeros(WaveformPara.DataPadding,1)];
|
||||||
|
%---------------------------------------------
|
||||||
|
dataMod = qammod(tx_padded_bit,WaveformPara.Mod,'InputType','bit');
|
||||||
|
WaveformPara.Power_sym = mean(abs(dataMod).^2);
|
||||||
|
dataMod = reshape(dataMod,WaveformPara.UsedSubcarrier,[]);
|
||||||
|
%% 获取信道响应 %假设已知前一时刻的信号
|
||||||
|
% 生成信道响应
|
||||||
|
N_carriers = WaveformPara.N_FFT;
|
||||||
|
channel_response=sqrt(1/2)*(randn(1,N_carriers)+1i*randn(1,N_carriers));
|
||||||
|
% 窗的数目
|
||||||
|
N_windows = 8;
|
||||||
|
% 定义量化水平总数
|
||||||
|
N_level = 10;
|
||||||
|
% 最小CP值,外部条件,取决于最大延迟拓展,有最小CP值>最大延迟拓展
|
||||||
|
min_len_CP = 30;
|
||||||
|
% 测试函数
|
||||||
|
CPset = Generate_CP(channel_response,N_windows,N_level,min_len_CP);
|
||||||
|
|
||||||
|
% 物理层加密
|
||||||
|
[serialOFDMsym,WaveformPara.pilot,myFrameLen] = tx_FFTSymbolGen_PilotBlockPN(dataMod,WaveformPara,CPset); % 加CP的地方
|
||||||
|
WaveformPara.Power_sig = mean(abs(serialOFDMsym).^2);
|
||||||
|
[WaveformPara.preamble,WaveformPara.c1,WaveformPara.c2] = ...
|
||||||
|
generatePreamble(WaveformPara,WaveformPara.Power_sig); % hb:这里前导码的目的是什么?
|
||||||
|
txSignal = [WaveformPara.preamble;serialOFDMsym];
|
||||||
|
% RFSignal = RFimpairment(txSignal, FreqCarrier);
|
||||||
|
|
||||||
|
% 分两块,发送 接收
|
||||||
|
%% Channel
|
||||||
|
[rxSignal,ChanPara] = PassChan(txSignal,WaveformPara,SysParameters,ChanPara,seed_set(2));
|
||||||
|
|
||||||
|
% SIR = InterfCal(rxSignal,ChanPara);
|
||||||
|
|
||||||
|
|
||||||
|
%% RX
|
||||||
|
[rxSignal_sync,SyncErr] = rxSyncSC(rxSignal,WaveformPara,myFrameLen);
|
||||||
|
[rxDataModLs] = rx_PilotBlockChanEst(rxSignal_sync,ChanPara,WaveformPara,CPset,SysParameters); % 去CP的地方
|
||||||
|
dataDemod = qamdemod(rxDataModLs,WaveformPara.Mod,'OutputType','approxllr', ...
|
||||||
|
'UnitAveragePower',false,'NoiseVariance',ChanPara.N0);
|
||||||
|
dataDePadded = dataDemod(1:end - WaveformPara.DataPadding);
|
||||||
|
tb = 8;
|
||||||
|
decoded = vitdec(dataDePadded,trellis,tb,'trunc','unquant',WaveformPara.puncpat);
|
||||||
|
|
||||||
|
[rx,PER] = RX_CRC32_deScramble(decoded);
|
||||||
|
[numErrors,BER] = biterr(dataPacketBits,rx);
|
||||||
|
end
|
||||||
|
|
||||||
|
%%
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
73
WaveAdp/Generate_CP.m
Normal file
73
WaveAdp/Generate_CP.m
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
function [len_CP] = Generate_CP(channel_response,N_windows,N_level,min_len_CP)
|
||||||
|
% 产生CP长度的函数
|
||||||
|
% 在该方法中,假设将要发送的OFDM符号的数量等于H_bs中窗的数目。
|
||||||
|
% 输入channel_response 信道响应;N_windows 需要划窗的个数;N_level 量化等级;
|
||||||
|
% min_len_CP,最小CP取决于最大延迟拓展,有最小CP值>最大延迟拓展
|
||||||
|
% 输出CP的长度向量,其长度等于窗的个数
|
||||||
|
|
||||||
|
% 子载波个数
|
||||||
|
N_carriers = length(channel_response);
|
||||||
|
% 窗的长度
|
||||||
|
Len_windows = N_carriers / N_windows;
|
||||||
|
|
||||||
|
% 对信道增益进行降序排序并记录索引
|
||||||
|
[channel_gain, sorted_indices] = sort(abs(channel_response), 'descend');%
|
||||||
|
G_max = max(channel_gain);
|
||||||
|
G_min = min(channel_gain);
|
||||||
|
|
||||||
|
% 距离水平
|
||||||
|
D_L = (G_max-G_min)/N_level;
|
||||||
|
|
||||||
|
% 计算每个子载波对应的等级
|
||||||
|
level_k = zeros(1,N_carriers);
|
||||||
|
for i = 1:N_carriers
|
||||||
|
% 边界值处理
|
||||||
|
if channel_gain(i) <= G_min
|
||||||
|
level_k(i) = 1;
|
||||||
|
elseif channel_gain(i) >= G_max
|
||||||
|
level_k(i) = N_level;
|
||||||
|
% 根据式(3)的变形,可以得到权重等级
|
||||||
|
else
|
||||||
|
level_k(i) = ceil((channel_gain(i) - G_min)/D_L);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
% 根据式(2)计算子载波权值
|
||||||
|
weight_k = 2*level_k-1;
|
||||||
|
|
||||||
|
% 对每个窗进行计算,获得该窗下对应的CP长度
|
||||||
|
weight_matrix = zeros(N_windows,Len_windows);
|
||||||
|
choose_matrix = zeros(N_windows,Len_windows);
|
||||||
|
len_CP = zeros(1,N_windows);
|
||||||
|
for i = 1:N_windows
|
||||||
|
|
||||||
|
weight_matrix(i,:) = weight_k((i-1)*Len_windows+1:i*Len_windows);% 将权重向量转变为权重矩阵,其中每一行为每一个窗的权重
|
||||||
|
current_CP = weight_matrix(i,1);% 临时变量,用于权重相加
|
||||||
|
choose_matrix(i,1) = current_CP;% 选择矩阵,记录相加权重的值
|
||||||
|
for j = 2:Len_windows
|
||||||
|
% 累加权重,进行判断
|
||||||
|
if current_CP <= min_len_CP
|
||||||
|
current_CP = current_CP + weight_matrix(i,j);
|
||||||
|
choose_matrix(i,j) = weight_matrix(i,j);
|
||||||
|
% 边界条件处理
|
||||||
|
if j == Len_windows
|
||||||
|
if current_CP <= min_len_CP % 仍未满足条件
|
||||||
|
len_CP(i) = min_len_CP;
|
||||||
|
break;
|
||||||
|
else
|
||||||
|
len_CP(i) = current_CP;% 满足条件
|
||||||
|
break;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
% current_CP > min_len_CP,直接赋值
|
||||||
|
else
|
||||||
|
len_CP(i) = current_CP;
|
||||||
|
break;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
end
|
BIN
WaveAdp/NumerologySet.mat
Normal file
BIN
WaveAdp/NumerologySet.mat
Normal file
Binary file not shown.
18
WaveAdp/PassChan.m
Normal file
18
WaveAdp/PassChan.m
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
function [chanOut,ChanPara] = PassChan(dataIn,WaveformPara,SysParameters,ChanPara,seed)
|
||||||
|
|
||||||
|
Chan = comm.RayleighChannel(...
|
||||||
|
'SampleRate',ChanPara.SampleFs, ...
|
||||||
|
'PathDelays', ChanPara.delay, ...
|
||||||
|
'AveragePathGains', ChanPara.PDP, ...
|
||||||
|
'NormalizePathGains',true, ...
|
||||||
|
'MaximumDopplerShift',floor(ChanPara.MaximumDopplerShift), ...
|
||||||
|
'DopplerSpectrum',doppler(ChanPara.doppler), ...
|
||||||
|
'PathGainsOutputPort',SysParameters.ShowPathGain);
|
||||||
|
[rAddMultipath,~] = Chan(dataIn);
|
||||||
|
% rAddCFO = rAddMultipath.*exp(sqrt(-1)*2*pi*(1:length(rAddMultipath))'*ChanPara.epsilon/N_FFT);
|
||||||
|
SNR = ChanPara.SNR;
|
||||||
|
ChanPara.N0 = WaveformPara.Power_sig/10^(SNR/10);
|
||||||
|
rAddAWGN = awgn(rAddMultipath,SNR,'measured');
|
||||||
|
chanOut = [sqrt(ChanPara.N0)*(randn(400,1)+1i*randn(400,1));rAddAWGN];
|
||||||
|
|
||||||
|
end
|
115
WaveAdp/RX.m
Normal file
115
WaveAdp/RX.m
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
%% RX for labview
|
||||||
|
clc;
|
||||||
|
close all;
|
||||||
|
clear ;
|
||||||
|
%% 接收端输入测试数据
|
||||||
|
receiveAntennasNum = 1;
|
||||||
|
receiveBandwidth = 20e6;
|
||||||
|
syncAlgo = 'first';
|
||||||
|
chanEstiAlgo = 'first';
|
||||||
|
equalizeAlgo = 'first';
|
||||||
|
demodMode = 'first';
|
||||||
|
interpCodeAlgo = 'first';
|
||||||
|
|
||||||
|
%% 接收端输入端接口
|
||||||
|
rxInput.receiveAntennasNum = receiveAntennasNum; % 1 or 2
|
||||||
|
rxInput.receiveBandwidth = receiveBandwidth;% 10~20M
|
||||||
|
rxInput.syncAlgo = syncAlgo;% 接口,输入类型为string
|
||||||
|
rxInput.chanEstiAlgo = chanEstiAlgo;% 接口,输入类型为string
|
||||||
|
rxInput.equalizeAlgo = equalizeAlgo;% 接口,输入类型为string
|
||||||
|
rxInput.demodMode = demodMode;% 接口,输入类型为string
|
||||||
|
rxInput.interpCodeAlgo = interpCodeAlgo;% 接口,输入类型为string
|
||||||
|
|
||||||
|
|
||||||
|
%% 测试数据,发送端波形参数
|
||||||
|
userNum = 1;
|
||||||
|
fileType = 'text';
|
||||||
|
encryptMode = 'encryptMode';
|
||||||
|
antennasNum = 1;
|
||||||
|
centerFreq = 2450e6;
|
||||||
|
sendBandwidth = 5e6;
|
||||||
|
fftNum = 128;
|
||||||
|
CPratio = 0.25;
|
||||||
|
pilotInterval = 3;
|
||||||
|
% MCS_set=[2,2;4,2;4,4;16,2;16,4;64,3;64,4;64,6];% 加密算法需要做一个适配,CHB,3.19
|
||||||
|
MCS = [16,4];
|
||||||
|
subcarriersNum = 128; % 待适配
|
||||||
|
|
||||||
|
%% 接收端 计算发送端的一切状态
|
||||||
|
txInput.userNum = userNum; % 1 or 2
|
||||||
|
txInput.fileType = fileType; % 'text' or 'picture'
|
||||||
|
|
||||||
|
txInput.encryptMode = encryptMode; % 'encrypt' or 'not encrypt'
|
||||||
|
txInput.antennasNum = antennasNum; % 1 or 2
|
||||||
|
txInput.centerFreq = centerFreq; % 500MHz~2.4G
|
||||||
|
txInput.sendBandwidth = sendBandwidth; % 20~40MHz
|
||||||
|
txInput.fftNum = fftNum;% 128 or 256 or 512
|
||||||
|
txInput.CPratio = CPratio; % 0.25 or 0.125 or 0.0625
|
||||||
|
txInput.pilotInterval = pilotInterval; % 3 5 7
|
||||||
|
txInput.MCS = MCS; % a set [2,2;4,2;4,4;16,2;16,4;64,3;64,4;64,6]
|
||||||
|
txInput.subcarriersNum = subcarriersNum;% 52 or 106 or 242
|
||||||
|
|
||||||
|
PacketSize = 200;
|
||||||
|
NumerologySel = [txInput.fftNum,txInput.CPratio,txInput.pilotInterval];
|
||||||
|
MCS_no = txInput.MCS;
|
||||||
|
|
||||||
|
[SysParameters,WaveformPara] = WaveformNumerologyCal(PacketSize,NumerologySel,MCS_no);
|
||||||
|
|
||||||
|
seed_set = [1 2 3];
|
||||||
|
rng(seed_set(1),'twister');
|
||||||
|
dataPacketBits = randi([0 1],WaveformPara.Payload,1);
|
||||||
|
scrData = TX_CRC32_Scramble(dataPacketBits);
|
||||||
|
trellis = poly2trellis(7,[171 133]);
|
||||||
|
tx_encoded_bit = convenc(scrData,trellis,WaveformPara.puncpat);
|
||||||
|
tx_padded_bit = [tx_encoded_bit;zeros(WaveformPara.DataPadding,1)];
|
||||||
|
%---------------------------------------------
|
||||||
|
dataMod = qammod(tx_padded_bit,WaveformPara.Mod,'InputType','bit');
|
||||||
|
WaveformPara.Power_sym = mean(abs(dataMod).^2);
|
||||||
|
dataMod = reshape(dataMod,WaveformPara.UsedSubcarrier,[]);
|
||||||
|
|
||||||
|
%% 获取信道响应 %假设已知前一时刻的信号
|
||||||
|
% 生成信道响应
|
||||||
|
N_carriers = WaveformPara.N_FFT;
|
||||||
|
channel_response=sqrt(1/2)*(randn(1,N_carriers)+1i*randn(1,N_carriers));
|
||||||
|
N_windows = 8;
|
||||||
|
N_level = 10;
|
||||||
|
min_len_CP = 30;
|
||||||
|
CPset = Generate_CP(channel_response,N_windows,N_level,min_len_CP);
|
||||||
|
[serialOFDMsym,WaveformPara.pilot,myFrameLen] = tx_FFTSymbolGen_PilotBlockPN(dataMod,WaveformPara,CPset);
|
||||||
|
WaveformPara.Power_sig = mean(abs(serialOFDMsym).^2);
|
||||||
|
[WaveformPara.preamble,WaveformPara.c1,WaveformPara.c2] = ...
|
||||||
|
generatePreamble(WaveformPara,WaveformPara.Power_sig);
|
||||||
|
%% 输入数据,接收端
|
||||||
|
|
||||||
|
load('rxdata5normalized.mat')
|
||||||
|
|
||||||
|
% rxSignal = rxSignal(5382:8680)';
|
||||||
|
% rxSignal = downsample(rxSignal, 2)';%data1 part
|
||||||
|
|
||||||
|
% rxSignal = rxSignal(5128:7889)';%data2 part
|
||||||
|
|
||||||
|
rxSignal = rxSignal(8500:10500)';
|
||||||
|
|
||||||
|
[rxSignal_sync,SyncErr] = rxSyncSC(rxSignal,WaveformPara,myFrameLen);
|
||||||
|
[rxDataModLs] = rx_PilotBlockChanEstForLabview(rxSignal_sync,WaveformPara,CPset); % 去CP的地方
|
||||||
|
dataDemod = qamdemod(rxDataModLs,WaveformPara.Mod,'OutputType','approxllr', ...
|
||||||
|
'UnitAveragePower',false,'NoiseVariance',0.0243);%ChanPara.N0
|
||||||
|
dataDePadded = dataDemod(1:end - WaveformPara.DataPadding);
|
||||||
|
tb = 8;
|
||||||
|
decoded = vitdec(dataDePadded,trellis,tb,'trunc','unquant',WaveformPara.puncpat);
|
||||||
|
|
||||||
|
[rxBits,PER] = RX_CRC32_deScramble(decoded);% 丢包率
|
||||||
|
[numErrors,BER] = biterr(dataPacketBits,rxBits);
|
||||||
|
|
||||||
|
%% 接收端输出接口
|
||||||
|
rxOutput.delaySpread = 0; % 接口,输出类型为double
|
||||||
|
rxOutput.SNR = 0;% 接口,输出类型为double
|
||||||
|
rxOutput.RSSI = 0;% 接口,输出类型为double
|
||||||
|
rxOutput.BER = BER;% 输出类型为double
|
||||||
|
rxOutput.PER = PER;% 输出类型为double
|
||||||
|
rxOutput.EVM = 0;% 接口,输出类型为double
|
||||||
|
rxOutput.phaseNoise = 0;% 接口,输出类型为double
|
||||||
|
|
||||||
|
BER
|
||||||
|
PER
|
||||||
|
SyncErr
|
15
WaveAdp/RX_CRC32_deScramble.m
Normal file
15
WaveAdp/RX_CRC32_deScramble.m
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
function [rx,frmError] = RX_CRC32_deScramble(dataPacketBits)
|
||||||
|
|
||||||
|
descrambler = comm.Descrambler(2,[1 0 0 0 0 0 1 0 1], ...
|
||||||
|
zeros(8,1));
|
||||||
|
deScrData = descrambler(dataPacketBits);
|
||||||
|
|
||||||
|
poly = [32,26,23,22,16,12,11,10,8,7,5,4,2,1,0];
|
||||||
|
crcdetector = comm.CRCDetector(...
|
||||||
|
'Polynomial', poly, ...
|
||||||
|
'InitialConditions', 1, ...
|
||||||
|
'DirectMethod', true, ...
|
||||||
|
'FinalXOR', 1);
|
||||||
|
[rx,frmError] = crcdetector(deScrData);
|
||||||
|
|
||||||
|
end
|
124
WaveAdp/RX_forPreamble.m
Normal file
124
WaveAdp/RX_forPreamble.m
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
%% RX for labview
|
||||||
|
clc;
|
||||||
|
close all;
|
||||||
|
clear ;
|
||||||
|
%% 接收端输入测试数据
|
||||||
|
receiveAntennasNum = 1;
|
||||||
|
receiveBandwidth = 20e6;
|
||||||
|
syncAlgo = 'first';
|
||||||
|
chanEstiAlgo = 'first';
|
||||||
|
equalizeAlgo = 'first';
|
||||||
|
demodMode = 'first';
|
||||||
|
interpCodeAlgo = 'first';
|
||||||
|
|
||||||
|
%% 接收端输入端接口
|
||||||
|
rxInput.receiveAntennasNum = receiveAntennasNum; % 1 or 2
|
||||||
|
rxInput.receiveBandwidth = receiveBandwidth;% 10~20M
|
||||||
|
rxInput.syncAlgo = syncAlgo;% 接口,输入类型为string
|
||||||
|
rxInput.chanEstiAlgo = chanEstiAlgo;% 接口,输入类型为string
|
||||||
|
rxInput.equalizeAlgo = equalizeAlgo;% 接口,输入类型为string
|
||||||
|
rxInput.demodMode = demodMode;% 接口,输入类型为string
|
||||||
|
rxInput.interpCodeAlgo = interpCodeAlgo;% 接口,输入类型为string
|
||||||
|
|
||||||
|
|
||||||
|
%% 测试数据,发送端波形参数
|
||||||
|
userNum = 1;
|
||||||
|
fileType = 'text';
|
||||||
|
encryptMode = 'encryptMode';
|
||||||
|
antennasNum = 1;
|
||||||
|
centerFreq = 2450e6;
|
||||||
|
sendBandwidth = 5e6;
|
||||||
|
fftNum = 128;
|
||||||
|
CPratio = 0.25;
|
||||||
|
pilotInterval = 3;
|
||||||
|
% MCS_set=[2,2;4,2;4,4;16,2;16,4;64,3;64,4;64,6];% 加密算法需要做一个适配,CHB,3.19
|
||||||
|
MCS = [16,4];
|
||||||
|
subcarriersNum = 128; % 待适配
|
||||||
|
|
||||||
|
%% 接收端 计算发送端的一切状态
|
||||||
|
txInput.userNum = userNum; % 1 or 2
|
||||||
|
txInput.fileType = fileType; % 'text' or 'picture'
|
||||||
|
|
||||||
|
txInput.encryptMode = encryptMode; % 'encrypt' or 'not encrypt'
|
||||||
|
txInput.antennasNum = antennasNum; % 1 or 2
|
||||||
|
txInput.centerFreq = centerFreq; % 500MHz~2.4G
|
||||||
|
txInput.sendBandwidth = sendBandwidth; % 20~40MHz
|
||||||
|
txInput.fftNum = fftNum;% 128 or 256 or 512
|
||||||
|
txInput.CPratio = CPratio; % 0.25 or 0.125 or 0.0625
|
||||||
|
txInput.pilotInterval = pilotInterval; % 3 5 7
|
||||||
|
txInput.MCS = MCS; % a set [2,2;4,2;4,4;16,2;16,4;64,3;64,4;64,6]
|
||||||
|
txInput.subcarriersNum = subcarriersNum;% 52 or 106 or 242
|
||||||
|
|
||||||
|
PacketSize = 200;
|
||||||
|
NumerologySel = [txInput.fftNum,txInput.CPratio,txInput.pilotInterval];
|
||||||
|
MCS_no = txInput.MCS;
|
||||||
|
|
||||||
|
[SysParameters,WaveformPara] = WaveformNumerologyCal(PacketSize,NumerologySel,MCS_no);
|
||||||
|
|
||||||
|
seed_set = [1 2 3];
|
||||||
|
rng(seed_set(1),'twister');
|
||||||
|
dataPacketBits = randi([0 1],WaveformPara.Payload,1);
|
||||||
|
scrData = TX_CRC32_Scramble(dataPacketBits);
|
||||||
|
trellis = poly2trellis(7,[171 133]);
|
||||||
|
tx_encoded_bit = convenc(scrData,trellis,WaveformPara.puncpat);
|
||||||
|
tx_padded_bit = [tx_encoded_bit;zeros(WaveformPara.DataPadding,1)];
|
||||||
|
%---------------------------------------------
|
||||||
|
dataMod = qammod(tx_padded_bit,WaveformPara.Mod,'InputType','bit');
|
||||||
|
WaveformPara.Power_sym = mean(abs(dataMod).^2);
|
||||||
|
dataMod = reshape(dataMod,WaveformPara.UsedSubcarrier,[]);
|
||||||
|
|
||||||
|
%% 获取信道响应 %假设已知前一时刻的信号
|
||||||
|
% 生成信道响应
|
||||||
|
N_carriers = WaveformPara.N_FFT;
|
||||||
|
channel_response=sqrt(1/2)*(randn(1,N_carriers)+1i*randn(1,N_carriers));
|
||||||
|
N_windows = 8;
|
||||||
|
N_level = 10;
|
||||||
|
min_len_CP = 30;
|
||||||
|
CPset = Generate_CP(channel_response,N_windows,N_level,min_len_CP);
|
||||||
|
[serialOFDMsym,WaveformPara.pilot,serialFrameLen] = tx_FFTSymbolGen_PilotBlockPN(dataMod,WaveformPara,CPset);
|
||||||
|
WaveformPara.Power_sig = mean(abs(serialOFDMsym).^2);
|
||||||
|
[WaveformPara.preamble,WaveformPara.c1,WaveformPara.c2] = ...
|
||||||
|
generatePreamble(WaveformPara,WaveformPara.Power_sig);
|
||||||
|
%% 输入数据,接收端
|
||||||
|
% load('preambleData.mat')
|
||||||
|
load('rxdata6normalizedzero.mat')
|
||||||
|
|
||||||
|
% A = 20*log10(abs(fft(rxSignal)));
|
||||||
|
% plot(A);
|
||||||
|
% rxSignal = rxSignal(5382:8680)';
|
||||||
|
% rxSignal = downsample(rxSignal, 2)';%data1 part
|
||||||
|
|
||||||
|
% rxSignal = rxSignal(5128:7889)';%data2 part
|
||||||
|
|
||||||
|
% rxSignal = rxSignal(4500+370:7000)';%data4 part
|
||||||
|
|
||||||
|
rxSignal = rxSignal(14000:17000)'/sqrt(mean(abs(rxSignal(14000:17000).^2)));
|
||||||
|
rxSignal=awgn(rxSignal,20,mean(abs(rxSignal.^2)));
|
||||||
|
% rxSignal = txSignalNormalized;
|
||||||
|
% [rxSignal_sync,SyncErr] = rxSyncSC(rxSignal,WaveformPara,myFrameLen);
|
||||||
|
|
||||||
|
[rxSignal_sync,MCS,PSDULength,failCheck,rec_frameNo,estNumerlogy,numeroError] = rx_preambleprocess(rxSignal);
|
||||||
|
rxSignal_sync = rxSignal_sync(1:serialFrameLen);
|
||||||
|
|
||||||
|
[rxDataModLs] = rx_PilotBlockChanEstForLabview(rxSignal_sync,WaveformPara,CPset); % 去CP的地方
|
||||||
|
dataDemod = qamdemod(rxDataModLs,WaveformPara.Mod,'OutputType','approxllr', ...
|
||||||
|
'UnitAveragePower',false,'NoiseVariance',0.0243);%ChanPara.N0
|
||||||
|
dataDePadded = dataDemod(1:end - WaveformPara.DataPadding);
|
||||||
|
tb = 8;
|
||||||
|
decoded = vitdec(dataDePadded,trellis,tb,'trunc','unquant',WaveformPara.puncpat);
|
||||||
|
|
||||||
|
[rxBits,PER] = RX_CRC32_deScramble(decoded);% 丢包率
|
||||||
|
[numErrors,BER] = biterr(dataPacketBits,rxBits);
|
||||||
|
|
||||||
|
%% 接收端输出接口
|
||||||
|
rxOutput.delaySpread = 0; % 接口,输出类型为double
|
||||||
|
rxOutput.SNR = 0;% 接口,输出类型为double
|
||||||
|
rxOutput.RSSI = 0;% 接口,输出类型为double
|
||||||
|
rxOutput.BER = BER;% 输出类型为double
|
||||||
|
rxOutput.PER = PER;% 输出类型为double
|
||||||
|
rxOutput.EVM = 0;% 接口,输出类型为double
|
||||||
|
rxOutput.phaseNoise = 0;% 接口,输出类型为double
|
||||||
|
|
||||||
|
BER
|
||||||
|
PER
|
||||||
|
% SyncErr
|
BIN
WaveAdp/STS_M32Q16.mat
Normal file
BIN
WaveAdp/STS_M32Q16.mat
Normal file
Binary file not shown.
68
WaveAdp/STS_demod.m
Normal file
68
WaveAdp/STS_demod.m
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
function [estNumerlogy,frmError] = STS_demod(rx_STF)
|
||||||
|
M=32;Q=16;OVR=1;
|
||||||
|
load STS_M32Q16.mat theta_mod v_mod STS_freq
|
||||||
|
|
||||||
|
STS_NUM = 9;
|
||||||
|
RX_re = reshape(rx_STF(17:end),[],STS_NUM);
|
||||||
|
STS_f = fftshift(fft(RX_re,16,1));
|
||||||
|
STS_freq_sk = STS_f([3:8,10:15],:);
|
||||||
|
theta_est = mod(angle(STS_freq_sk(2:end,:)./STS_freq_sk(1:end-1,:)),2*pi);
|
||||||
|
|
||||||
|
mmse_est = zeros(Q,STS_NUM);
|
||||||
|
for iii = 1:STS_NUM
|
||||||
|
for ii = 1:Q
|
||||||
|
mmse_tmp = abs(theta_est(:,iii)-theta_mod(ii,:).');
|
||||||
|
mmse_est(ii,iii) = norm(min([mmse_tmp,2*pi - mmse_tmp],[],2))^2;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
mmse_est2 = sum(mmse_est,2);
|
||||||
|
v_est_no = find(mmse_est2==min(mmse_est2));
|
||||||
|
v_est = exp(j*v_mod(v_est_no(1)));
|
||||||
|
%%------demodulate phi
|
||||||
|
STS_freq_sk = STS_freq_sk./abs(STS_freq_sk);
|
||||||
|
% [~,STS_ref] = preamble_modu1(theta_mod(v_est_no(1),:), 0, OVR);
|
||||||
|
STS_ref = STS_freq(:,v_est_no(1),1);
|
||||||
|
STS_ref = STS_ref./abs(STS_ref);
|
||||||
|
phi_est_angle = mod(angle(sum(sum((STS_freq_sk(:,1:STS_NUM)./STS_ref)))),2*pi);
|
||||||
|
phi_est = exp(j*phi_est_angle);
|
||||||
|
|
||||||
|
% demap v and phi to Bits using pskmod
|
||||||
|
v_data_est = pskdemod(v_est,Q,0,'gray');
|
||||||
|
dePreambleQ = de2bi(v_data_est,log2(Q));
|
||||||
|
|
||||||
|
phi_data_est = pskdemod(phi_est,M,0,'gray');
|
||||||
|
dePreambleM = de2bi(phi_data_est,log2(M));
|
||||||
|
|
||||||
|
% CRC
|
||||||
|
poly = 'z4+z3+z2+z+1';
|
||||||
|
crcdetector = comm.CRCDetector(poly);
|
||||||
|
codeword = [dePreambleM,dePreambleQ];
|
||||||
|
[msg,frmError] = crcdetector(codeword.');
|
||||||
|
estNumerlogy = bi2de(msg.')+1;
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
%%
|
||||||
|
function [STS_time,STS_freq] = preamble_modu1(theta, phi, OVR)
|
||||||
|
% N_FFT =64;
|
||||||
|
s_k(1) = 1*exp(j*phi);
|
||||||
|
s_k(1) = sqrt(2)/abs(s_k(1))*s_k(1);
|
||||||
|
for i = 1:11
|
||||||
|
s_k(i+1) = s_k(i)*exp(j*theta(i));
|
||||||
|
end
|
||||||
|
STS_LOC = [9,13,17,21,25,29,37,41,45,49,53,57];
|
||||||
|
Short_preamble_slot_Frequency = zeros(1,64); % [1x64]
|
||||||
|
Short_preamble_slot_Frequency(STS_LOC) = s_k;
|
||||||
|
STS_freq = ifftshift(Short_preamble_slot_Frequency);
|
||||||
|
STS = ifft([STS_freq(1:32),zeros(1,64*(OVR-1)),STS_freq(33:64)])*sqrt(64);
|
||||||
|
STS = sqrt(1/mean(abs(STS).^2))*STS;
|
||||||
|
|
||||||
|
STS_f = fft(STS);
|
||||||
|
STS_f = [STS_f(1:32),STS_f((end-31:end))];
|
||||||
|
STS_freq = fftshift(STS_f);
|
||||||
|
|
||||||
|
STS_time = STS(1:16*OVR);
|
||||||
|
STS_freq = STS_freq(STS_LOC);
|
||||||
|
% STS_dpsk = mod(angle(STS_freq((2:end))./STS_freq((1:end-1))),2*pi);
|
||||||
|
% STS_dpsk(theta==0) = min([STS_dpsk(theta==0);2*pi - STS_dpsk(theta==0)],[],1);
|
||||||
|
end
|
28
WaveAdp/STS_modulation.m
Normal file
28
WaveAdp/STS_modulation.m
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
function tx_STF = STS_modulation(Numerology)
|
||||||
|
% total 9bits 5 for Numerology 4 for crc
|
||||||
|
% input is the No. of Numerology 0~26
|
||||||
|
|
||||||
|
preamblebit = de2bi(Numerology-1,5);
|
||||||
|
|
||||||
|
% CRC
|
||||||
|
poly = 'z4+z3+z2+z+1';
|
||||||
|
crcgenerator = comm.CRCGenerator(poly);
|
||||||
|
codeword = crcgenerator(preamblebit.');
|
||||||
|
crccode = codeword(6:end).';
|
||||||
|
% preamble mod
|
||||||
|
M=32;Q=16;
|
||||||
|
theta0 = [0 0 0 pi 0 pi pi 0 pi pi pi];
|
||||||
|
phi_mod = [0:1/M*2*pi:2*pi-1/M*2*pi];
|
||||||
|
v_mod = [0:1/Q*2*pi:2*pi-1/Q*2*pi];
|
||||||
|
|
||||||
|
load STS_M32Q16.mat STS_mod
|
||||||
|
|
||||||
|
phi_data = pskmod(bi2de(preamblebit),M,0,'gray');% for M
|
||||||
|
v_data = pskmod(bi2de(crccode),Q,0,'gray');% for Q
|
||||||
|
|
||||||
|
[~,phi_no] = min(abs(phi_mod-mod(angle(phi_data),2*pi)));
|
||||||
|
[~,v_no] = min(abs(v_mod-mod(angle(v_data),2*pi)));
|
||||||
|
STF = STS_mod(:,v_no,phi_no);
|
||||||
|
tx_STF = repmat(STF,10,1);
|
||||||
|
|
||||||
|
end
|
110
WaveAdp/TX.m
Normal file
110
WaveAdp/TX.m
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
%% TX for labview
|
||||||
|
clc;
|
||||||
|
close all;
|
||||||
|
clear ;
|
||||||
|
|
||||||
|
%% 测试数据,输入
|
||||||
|
userNum = 1;
|
||||||
|
fileType = 'text';
|
||||||
|
encryptMode = 'encryptMode';
|
||||||
|
antennasNum = 1;
|
||||||
|
centerFreq = 2450e6;
|
||||||
|
sendBandwidth = 5e6;
|
||||||
|
fftNum = 128;
|
||||||
|
CPratio = 0.25;
|
||||||
|
pilotInterval = 3;
|
||||||
|
% MCS_set=[2,2;4,2;4,4;16,2;16,4;64,3;64,4;64,6];% 加密算法需要做一个适配,CHB,3.19
|
||||||
|
MCS = [16,4];
|
||||||
|
subcarriersNum = 128; % 待适配
|
||||||
|
|
||||||
|
|
||||||
|
%% 接口
|
||||||
|
txInput.userNum = userNum; % 1 or 2
|
||||||
|
txInput.fileType = fileType; % 'text' or 'picture'
|
||||||
|
|
||||||
|
txInput.encryptMode = encryptMode; % 'encrypt' or 'not encrypt'
|
||||||
|
txInput.antennasNum = antennasNum; % 1 or 2
|
||||||
|
txInput.centerFreq = centerFreq; % 500MHz~2.4G
|
||||||
|
txInput.sendBandwidth = sendBandwidth; % 20~40MHz
|
||||||
|
txInput.fftNum = fftNum;% 128 or 256 or 512
|
||||||
|
txInput.CPratio = CPratio; % 0.25 or 0.125 or 0.0625
|
||||||
|
txInput.pilotInterval = pilotInterval; % 3 5 7
|
||||||
|
txInput.MCS = MCS; % a set [2,2;4,2;4,4;16,2;16,4;64,3;64,4;64,6]
|
||||||
|
txInput.subcarriersNum = subcarriersNum;% 52 or 106 or 242
|
||||||
|
|
||||||
|
%% 产生发送数据
|
||||||
|
|
||||||
|
TimeStamp = [];
|
||||||
|
FreqCarrier = txInput.centerFreq;% 中心频点可调
|
||||||
|
Bandwidth = txInput.sendBandwidth;% 带宽可调 20~40e6
|
||||||
|
Ts = 1/Bandwidth;
|
||||||
|
% 仿真参数
|
||||||
|
Delay_set = [1:20]*Ts;
|
||||||
|
Velocity_set = [5:250];
|
||||||
|
SNR_set = [0:5:35];
|
||||||
|
|
||||||
|
FrameNum = 1;
|
||||||
|
PacketSize = 200; %
|
||||||
|
|
||||||
|
% load NumerologySet.mat NumerologySet
|
||||||
|
% NumerologySel = NumerologySet(1,:); % 128 0.25 3 % N_FFT; CPratio; PilotInterval
|
||||||
|
NumerologySel = [txInput.fftNum,txInput.CPratio,txInput.pilotInterval];
|
||||||
|
MCS_no = txInput.MCS;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
SNR = 25;
|
||||||
|
tau_d = Delay_set(randi([1 20]));
|
||||||
|
velocity = Velocity_set(randi([1 length(Velocity_set)]));
|
||||||
|
ChanPara = ChanStat(SNR, tau_d, velocity, Ts, FreqCarrier, TimeStamp);
|
||||||
|
|
||||||
|
% seed_set = randi([0 5000],FrameNum,3);
|
||||||
|
seed_set = [1 2 3];
|
||||||
|
|
||||||
|
[SysParameters,WaveformPara] = WaveformNumerologyCal(PacketSize,NumerologySel,MCS_no);
|
||||||
|
%% TX
|
||||||
|
rng(seed_set(1),'twister');
|
||||||
|
dataPacketBits = randi([0 1],WaveformPara.Payload,1);
|
||||||
|
scrData = TX_CRC32_Scramble(dataPacketBits);
|
||||||
|
trellis = poly2trellis(7,[171 133]);
|
||||||
|
tx_encoded_bit = convenc(scrData,trellis,WaveformPara.puncpat);
|
||||||
|
tx_padded_bit = [tx_encoded_bit;zeros(WaveformPara.DataPadding,1)];
|
||||||
|
%---------------------------------------------
|
||||||
|
dataMod = qammod(tx_padded_bit,WaveformPara.Mod,'InputType','bit');
|
||||||
|
WaveformPara.Power_sym = mean(abs(dataMod).^2);
|
||||||
|
dataMod = reshape(dataMod,WaveformPara.UsedSubcarrier,[]);
|
||||||
|
%% 获取信道响应 %假设已知前一时刻的信号
|
||||||
|
% 生成信道响应
|
||||||
|
N_carriers = WaveformPara.N_FFT;
|
||||||
|
channel_response=sqrt(1/2)*(randn(1,N_carriers)+1i*randn(1,N_carriers));
|
||||||
|
% 窗的数目
|
||||||
|
N_windows = 8;
|
||||||
|
% 定义量化水平总数
|
||||||
|
N_level = 10;
|
||||||
|
% 最小CP值,外部条件,取决于最大延迟拓展,有最小CP值>最大延迟拓展
|
||||||
|
min_len_CP = 30;
|
||||||
|
% 测试函数
|
||||||
|
CPset = Generate_CP(channel_response,N_windows,N_level,min_len_CP);
|
||||||
|
|
||||||
|
% 物理层加密
|
||||||
|
[serialOFDMsym,WaveformPara.pilot,myFrameLen] = tx_FFTSymbolGen_PilotBlockPN(dataMod,WaveformPara,CPset); % 加CP的地方
|
||||||
|
WaveformPara.Power_sig = mean(abs(serialOFDMsym).^2);
|
||||||
|
[WaveformPara.preamble,WaveformPara.c1,WaveformPara.c2] = ...
|
||||||
|
generatePreamble(WaveformPara,WaveformPara.Power_sig); % hb:这里前导码的目的是什么?
|
||||||
|
txSignal = [WaveformPara.preamble;serialOFDMsym];
|
||||||
|
txSignalNormalized = txSignal./max(abs(txSignal));
|
||||||
|
|
||||||
|
txOutput.sendSignal = txSignalNormalized;
|
||||||
|
|
||||||
|
% 待计算
|
||||||
|
txOutput.PAPR = 0;
|
||||||
|
|
||||||
|
%% Channel
|
||||||
|
% [rxSignal,ChanPara] = PassChan(txSignal,WaveformPara,SysParameters,ChanPara,seed_set(2));
|
||||||
|
% save('testInputDataForLabview.mat','rxSignal');
|
||||||
|
|
||||||
|
% SIR = InterfCal(rxSignal,ChanPara);
|
||||||
|
|
||||||
|
% A = 20*log10(abs(fft(txSignal)));
|
||||||
|
% plot(A);
|
||||||
|
|
13
WaveAdp/TX_CRC32_Scramble.m
Normal file
13
WaveAdp/TX_CRC32_Scramble.m
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
function scrData = TX_CRC32_Scramble(dataPacketBits)
|
||||||
|
poly = [32,26,23,22,16,12,11,10,8,7,5,4,2,1,0];
|
||||||
|
crcGen32 = comm.CRCGenerator(...
|
||||||
|
'Polynomial', poly, ...
|
||||||
|
'InitialConditions', 1, ...
|
||||||
|
'DirectMethod', true, ...
|
||||||
|
'FinalXOR', 1);
|
||||||
|
dataPacket = crcGen32(dataPacketBits);
|
||||||
|
|
||||||
|
scrambler = comm.Scrambler(2,[1 0 0 0 0 0 1 0 1], ...
|
||||||
|
zeros(8,1));
|
||||||
|
scrData = scrambler(dataPacket);
|
||||||
|
end
|
130
WaveAdp/TX_forPreamble.m
Normal file
130
WaveAdp/TX_forPreamble.m
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
%% TX for labview
|
||||||
|
clc;
|
||||||
|
close all;
|
||||||
|
clear ;
|
||||||
|
|
||||||
|
%% 测试数据,输入
|
||||||
|
userNum = 1;
|
||||||
|
fileType = 'text';
|
||||||
|
encryptMode = 'encryptMode';
|
||||||
|
antennasNum = 1;
|
||||||
|
centerFreq = 2450e6;
|
||||||
|
sendBandwidth = 5e6;
|
||||||
|
fftNum = 128;
|
||||||
|
CPratio = 0.25;
|
||||||
|
pilotInterval = 3;
|
||||||
|
% MCS_set=[2,2;4,2;4,4;16,2;16,4;64,3;64,4;64,6];% 加密算法需要做一个适配,CHB,3.19
|
||||||
|
MCS = [16,4];
|
||||||
|
subcarriersNum = 128; % 待适配
|
||||||
|
|
||||||
|
|
||||||
|
%% 接口
|
||||||
|
txInput.userNum = userNum; % 1 or 2
|
||||||
|
txInput.fileType = fileType; % 'text' or 'picture'
|
||||||
|
|
||||||
|
txInput.encryptMode = encryptMode; % 'encrypt' or 'not encrypt'
|
||||||
|
txInput.antennasNum = antennasNum; % 1 or 2
|
||||||
|
txInput.centerFreq = centerFreq; % 500MHz~2.4G
|
||||||
|
txInput.sendBandwidth = sendBandwidth; % 20~40MHz
|
||||||
|
txInput.fftNum = fftNum;% 128 or 256 or 512
|
||||||
|
txInput.CPratio = CPratio; % 0.25 or 0.125 or 0.0625
|
||||||
|
txInput.pilotInterval = pilotInterval; % 3 5 7
|
||||||
|
txInput.MCS = MCS; % a set [2,2;4,2;4,4;16,2;16,4;64,3;64,4;64,6]
|
||||||
|
txInput.subcarriersNum = subcarriersNum;% 52 or 106 or 242
|
||||||
|
|
||||||
|
%% 产生发送数据
|
||||||
|
|
||||||
|
TimeStamp = [];
|
||||||
|
FreqCarrier = txInput.centerFreq;% 中心频点可调
|
||||||
|
Bandwidth = txInput.sendBandwidth;% 带宽可调 20~40e6
|
||||||
|
Ts = 1/Bandwidth;
|
||||||
|
% 仿真参数
|
||||||
|
Delay_set = [1:20]*Ts;
|
||||||
|
Velocity_set = [5:250];
|
||||||
|
SNR_set = [0:5:35];
|
||||||
|
|
||||||
|
FrameNum = 1;
|
||||||
|
PacketSize = 200; %
|
||||||
|
|
||||||
|
% load NumerologySet.mat NumerologySet
|
||||||
|
% NumerologySel = NumerologySet(1,:); % 128 0.25 3 % N_FFT; CPratio; PilotInterval
|
||||||
|
NumerologySel = [txInput.fftNum,txInput.CPratio,txInput.pilotInterval];
|
||||||
|
MCS_no = txInput.MCS;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
SNR = 25;
|
||||||
|
tau_d = Delay_set(randi([1 20]));
|
||||||
|
velocity = Velocity_set(randi([1 length(Velocity_set)]));
|
||||||
|
ChanPara = ChanStat(SNR, tau_d, velocity, Ts, FreqCarrier, TimeStamp);
|
||||||
|
|
||||||
|
% seed_set = randi([0 5000],FrameNum,3);
|
||||||
|
seed_set = [1 2 3];
|
||||||
|
|
||||||
|
[SysParameters,WaveformPara] = WaveformNumerologyCal(PacketSize,NumerologySel,MCS_no);
|
||||||
|
%% TX
|
||||||
|
rng(seed_set(1),'twister');
|
||||||
|
dataPacketBits = randi([0 1],WaveformPara.Payload,1);
|
||||||
|
scrData = TX_CRC32_Scramble(dataPacketBits);
|
||||||
|
trellis = poly2trellis(7,[171 133]);
|
||||||
|
tx_encoded_bit = convenc(scrData,trellis,WaveformPara.puncpat);
|
||||||
|
tx_padded_bit = [tx_encoded_bit;zeros(WaveformPara.DataPadding,1)];
|
||||||
|
%---------------------------------------------
|
||||||
|
dataMod = qammod(tx_padded_bit,WaveformPara.Mod,'InputType','bit');
|
||||||
|
WaveformPara.Power_sym = mean(abs(dataMod).^2);
|
||||||
|
dataMod = reshape(dataMod,WaveformPara.UsedSubcarrier,[]);
|
||||||
|
%% 获取信道响应 %假设已知前一时刻的信号
|
||||||
|
% 生成信道响应
|
||||||
|
N_carriers = WaveformPara.N_FFT;
|
||||||
|
channel_response=sqrt(1/2)*(randn(1,N_carriers)+1i*randn(1,N_carriers));
|
||||||
|
% 窗的数目
|
||||||
|
N_windows = 8;
|
||||||
|
% 定义量化水平总数
|
||||||
|
N_level = 10;
|
||||||
|
% 最小CP值,外部条件,取决于最大延迟拓展,有最小CP值>最大延迟拓展
|
||||||
|
min_len_CP = 30;
|
||||||
|
% 测试函数
|
||||||
|
CPset = Generate_CP(channel_response,N_windows,N_level,min_len_CP);
|
||||||
|
|
||||||
|
% 物理层加密
|
||||||
|
[serialOFDMsym,WaveformPara.pilot,myFrameLen] = tx_FFTSymbolGen_PilotBlockPN(dataMod,WaveformPara,CPset); % 加CP的地方
|
||||||
|
WaveformPara.Power_sig = mean(abs(serialOFDMsym).^2);
|
||||||
|
|
||||||
|
|
||||||
|
% [WaveformPara.preamble,WaveformPara.c1,WaveformPara.c2] = ...
|
||||||
|
% generatePreamble(WaveformPara,WaveformPara.Power_sig); % hb:这里前导码的目的是什么?
|
||||||
|
% txSignal = [WaveformPara.preamble;serialOFDMsym];
|
||||||
|
|
||||||
|
%% Parameter
|
||||||
|
NumerologyNo = 1; % 1~27
|
||||||
|
FrameNo = 7;
|
||||||
|
% MCS_No = 3;
|
||||||
|
|
||||||
|
cfg = wlanNonHTConfig('SignalChannelBandwidth',true, ...
|
||||||
|
'BandwidthOperation','Static');
|
||||||
|
% cfg.MCS = MCS_No;
|
||||||
|
PacketSize = 200;
|
||||||
|
cfg.PSDULength = PacketSize; %0-4095
|
||||||
|
%% preamble
|
||||||
|
tx_STF = STS_modulation(NumerologyNo); % STF
|
||||||
|
tx_LTF = wlanLLTF(cfg); % LTF
|
||||||
|
[tx_SIG, tx_sigdata] = newLSIG(cfg,FrameNo);% SIG
|
||||||
|
% load('cfg.mat')
|
||||||
|
|
||||||
|
txSignal = [zeros(500,1);tx_STF;tx_LTF;tx_SIG;serialOFDMsym];
|
||||||
|
txSignalNormalized = txSignal./max(abs(txSignal));
|
||||||
|
txOutput.sendSignal = txSignalNormalized;
|
||||||
|
% 待计算
|
||||||
|
txOutput.PAPR = 0;
|
||||||
|
%% Channel
|
||||||
|
[rxSignal,ChanPara] = PassChan(txSignal,WaveformPara,SysParameters,ChanPara,seed_set(2));
|
||||||
|
save('testInputDataForLabview.mat','rxSignal');
|
||||||
|
|
||||||
|
% SIR = InterfCal(rxSignal,ChanPara);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
% A = 20*log10(abs(fft(txSignal)));
|
||||||
|
% plot(A);
|
||||||
|
|
68
WaveAdp/TestMAIN2022.m
Normal file
68
WaveAdp/TestMAIN2022.m
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
%% 适变框架-0318
|
||||||
|
% 2022.03.18
|
||||||
|
clear
|
||||||
|
%% Environment Scope
|
||||||
|
TimeStamp = [];
|
||||||
|
FreqCarrier = 2450e6;% 中心频点可调
|
||||||
|
Bandwidth = 5e6;% 带宽可调 20~40e6
|
||||||
|
Ts = 1/Bandwidth;
|
||||||
|
|
||||||
|
% 仿真参数
|
||||||
|
Delay_set = [1:20]*Ts;
|
||||||
|
Velocity_set = [5:250];
|
||||||
|
SNR_set = [0:5:35];
|
||||||
|
|
||||||
|
NodePair_num = 10;
|
||||||
|
|
||||||
|
load NumerologySet.mat NumerologySet
|
||||||
|
MCS_set=[2,2;4,2;4,4;16,2;16,4;64,3;64,4;64,6];
|
||||||
|
|
||||||
|
% isEncrypt = 1; % 为1时采用变CP加密传输,其他不加密
|
||||||
|
% 密钥安全算法,CP随机化算法
|
||||||
|
% 上层显示采用的波形参数(FFT,CP,导频)以及密钥算法等
|
||||||
|
|
||||||
|
|
||||||
|
%% Action
|
||||||
|
FrameNum = 1;
|
||||||
|
PacketSize = 200; %
|
||||||
|
NumerologySel = NumerologySet(1,:); % 128 0.25 3 % N_FFT; CPratio; PilotInterval
|
||||||
|
MCS_no = MCS_set(7,:);
|
||||||
|
|
||||||
|
%%
|
||||||
|
seed_set = randi([0 5000],FrameNum,3);
|
||||||
|
SyncER_statis = zeros(NodePair_num,FrameNum);
|
||||||
|
BER_statis = zeros(NodePair_num,FrameNum);
|
||||||
|
PER_statis = zeros(NodePair_num,FrameNum);
|
||||||
|
SIR = zeros(NodePair_num,FrameNum);
|
||||||
|
for vv = 1:NodePair_num
|
||||||
|
%% Environment Parameterant
|
||||||
|
SNR = 25;
|
||||||
|
tau_d = Delay_set(randi([1 20]));
|
||||||
|
velocity = Velocity_set(randi([1 length(Velocity_set)]));
|
||||||
|
ChanPara = ChanStat(SNR, tau_d, velocity, Ts, FreqCarrier, TimeStamp);
|
||||||
|
|
||||||
|
%% Reward
|
||||||
|
for mont = 1:FrameNum
|
||||||
|
[BER_statis(vv,mont),PER_statis(vv,mont),SyncER_statis(vv,mont)] = ...
|
||||||
|
ExecutedMAIN0701(PacketSize, NumerologySel, MCS_no, ChanPara, FreqCarrier, mont, seed_set(mont,:));
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
%% TMP
|
||||||
|
|
50
WaveAdp/WaveformNumerologyCal.m
Normal file
50
WaveAdp/WaveformNumerologyCal.m
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
|
||||||
|
function [SysParameters,WaveformPara] = WaveformNumerologyCal(PacketSize,NumerologySel,MCS_no)
|
||||||
|
%% 函数说明:计算系统链路的参数
|
||||||
|
N_FFT = NumerologySel(1); CPratio = NumerologySel(2); PilotInterval = NumerologySel(3);
|
||||||
|
%% 系统参数
|
||||||
|
SysParameters.ShowTiming =true;
|
||||||
|
SysParameters.ShowPAPR =false;
|
||||||
|
SysParameters.ShowFigure =true;
|
||||||
|
SysParameters.ShowPathGain =true;
|
||||||
|
SysParameters.SaveSimData =false;
|
||||||
|
|
||||||
|
WaveformPara.FrameType ='Data'; % Control为控制短帧,Data为数据帧,Audio为语音帧
|
||||||
|
|
||||||
|
% 波形参数
|
||||||
|
WaveformPara.PacketSize = PacketSize;
|
||||||
|
WaveformPara.Payload = WaveformPara.PacketSize*8;
|
||||||
|
WaveformPara.PayloadCRC = 32;
|
||||||
|
%--
|
||||||
|
WaveformPara.NullRatio = 1/4;
|
||||||
|
WaveformPara.N_FFT = N_FFT;
|
||||||
|
WaveformPara.CPratio = CPratio;
|
||||||
|
WaveformPara.PilotPattern = 'block';
|
||||||
|
WaveformPara.PilotInterval = PilotInterval;
|
||||||
|
|
||||||
|
WaveformPara.CP_Len = WaveformPara.N_FFT*WaveformPara.CPratio; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
WaveformPara.SymbolLen = WaveformPara.N_FFT*(WaveformPara.CPratio+1);
|
||||||
|
WaveformPara.UsedSubcarrier = (1-WaveformPara.NullRatio)*WaveformPara.N_FFT-1;
|
||||||
|
WaveformPara.NullSubcarrier = WaveformPara.NullRatio*WaveformPara.N_FFT;
|
||||||
|
%--
|
||||||
|
|
||||||
|
WaveformPara.Mod = MCS_no(1);
|
||||||
|
WaveformPara.Modulation = log2(WaveformPara.Mod);
|
||||||
|
WaveformPara.CodeRate = (MCS_no(2)-1)/MCS_no(2);
|
||||||
|
puncpat=[1,1,0,1,1,0,0,1,1,0];
|
||||||
|
WaveformPara.puncpat = puncpat(1:2*(MCS_no(2)-1));
|
||||||
|
%---------------------------------------------
|
||||||
|
|
||||||
|
WaveformPara.BitsPerSig = WaveformPara.UsedSubcarrier*WaveformPara.Modulation;
|
||||||
|
WaveformPara.DataFrame = ceil((WaveformPara.Payload+WaveformPara.PayloadCRC)/WaveformPara.CodeRate/WaveformPara.BitsPerSig);
|
||||||
|
WaveformPara.DataPadding = WaveformPara.DataFrame*WaveformPara.BitsPerSig - floor((WaveformPara.Payload+WaveformPara.PayloadCRC)/WaveformPara.CodeRate);
|
||||||
|
|
||||||
|
WaveformPara.PilotNum = ceil(WaveformPara.DataFrame/WaveformPara.PilotInterval);
|
||||||
|
WaveformPara.FrameSymNum = WaveformPara.DataFrame+WaveformPara.PilotNum;
|
||||||
|
|
||||||
|
WaveformPara.FrameConstelNum = WaveformPara.UsedSubcarrier * WaveformPara.DataFrame;
|
||||||
|
WaveformPara.FrameLen = WaveformPara.SymbolLen * WaveformPara.FrameSymNum;
|
||||||
|
|
||||||
|
WaveformPara.InterleavLen = 4080;
|
||||||
|
end
|
||||||
|
|
BIN
WaveAdp/cfg.mat
Normal file
BIN
WaveAdp/cfg.mat
Normal file
Binary file not shown.
47
WaveAdp/generatePreamble.m
Normal file
47
WaveAdp/generatePreamble.m
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
function [preamble,c1,c2] = generatePreamble(WaveformPara,Power)
|
||||||
|
|
||||||
|
N = WaveformPara.N_FFT;
|
||||||
|
L = WaveformPara.CP_Len;
|
||||||
|
pnSequence = comm.PNSequence('Polynomial',[8 6 5 4 0], ...
|
||||||
|
'SamplesPerFrame',N,'InitialConditions',[0 0 0 0 0 0 0 1]);
|
||||||
|
pnSeq1 = pnSequence();
|
||||||
|
|
||||||
|
Modulator = comm.QPSKModulator;
|
||||||
|
|
||||||
|
dataInMatrix1 = reshape(pnSeq1,N/2,2);
|
||||||
|
dataSymbolsIn1 = bi2de(dataInMatrix1);
|
||||||
|
|
||||||
|
pnSeq1 = Modulator(dataSymbolsIn1);
|
||||||
|
|
||||||
|
c1 = sqrt(2)*kron(pnSeq1,[1,0]');
|
||||||
|
|
||||||
|
pnSequence = comm.PNSequence('Polynomial',[8 6 5 4 0], ...
|
||||||
|
'SamplesPerFrame',N,'InitialConditions',[0 1 0 0 0 0 0 1]);
|
||||||
|
pnSeq2 = pnSequence();
|
||||||
|
dataInMatrix2 = reshape(pnSeq2,N/2,2);
|
||||||
|
dataSymbolsIn2 = bi2de(dataInMatrix2);
|
||||||
|
|
||||||
|
pnSeq2 = Modulator(dataSymbolsIn2);
|
||||||
|
|
||||||
|
pnSequence = comm.PNSequence('Polynomial',[8 6 5 4 0], ...
|
||||||
|
'SamplesPerFrame',N,'InitialConditions',[1 1 0 0 1 0 0 1]);
|
||||||
|
pnSeq3 = pnSequence();
|
||||||
|
dataInMatrix3 = reshape(pnSeq3,N/2,2);
|
||||||
|
dataSymbolsIn3 = bi2de(dataInMatrix3);
|
||||||
|
|
||||||
|
pnSeq3 = Modulator(dataSymbolsIn3);
|
||||||
|
|
||||||
|
c2 = zeros(N,1);
|
||||||
|
c2(1:2:N-1) = pnSeq2;
|
||||||
|
c2(2:2:N) = pnSeq3;
|
||||||
|
|
||||||
|
ofdmSymbol = ifft(c1,N)*sqrt(N);
|
||||||
|
cp = ofdmSymbol(length(ofdmSymbol)-L+1:end);
|
||||||
|
trainingSym1 = [cp;ofdmSymbol];
|
||||||
|
|
||||||
|
ofdmSymbol = ifft(c2,N)*sqrt(N);
|
||||||
|
cp = ofdmSymbol(length(ofdmSymbol)-L+1:end);
|
||||||
|
trainingSym2 = [cp;ofdmSymbol];
|
||||||
|
|
||||||
|
preamble = sqrt(Power)/sqrt(2)*([trainingSym1;trainingSym2]);
|
||||||
|
end
|
27
WaveAdp/helperFrequencyOffset.m
Normal file
27
WaveAdp/helperFrequencyOffset.m
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
function out = helperFrequencyOffset(in, fs, foffset)
|
||||||
|
%helperFrequencyOffset Apply a frequency offset to the input signal
|
||||||
|
%
|
||||||
|
% OUT = helperFrequencyOffset(IN, FS, FOFFSET) applies the specified
|
||||||
|
% frequency offset to the input signal.
|
||||||
|
%
|
||||||
|
% OUT is the frequency-offset output of the same size as IN.
|
||||||
|
% IN is the complex 2D array input.
|
||||||
|
% FS is the sampling rate in Hz (e.g. 80e6).
|
||||||
|
% FOFFSET is the frequency offset to apply to the input in Hz.
|
||||||
|
%
|
||||||
|
% See also comm.PhaseFrequencyOffset.
|
||||||
|
|
||||||
|
% Copyright 2015-2019 The MathWorks, Inc.
|
||||||
|
|
||||||
|
%#codegen
|
||||||
|
|
||||||
|
% Initialize output
|
||||||
|
out = complex(zeros(size(in)));
|
||||||
|
|
||||||
|
% Create vector of time samples
|
||||||
|
t = ((0:size(in,1)-1)/fs).';
|
||||||
|
|
||||||
|
% For each antenna, apply the frequency offset
|
||||||
|
for i = 1:size(in,2)
|
||||||
|
out(:,i) = in(:,i).*exp(1i*2*pi*foffset*t);
|
||||||
|
end
|
127
WaveAdp/mainForLabview.m
Normal file
127
WaveAdp/mainForLabview.m
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
%% simulation for labview
|
||||||
|
|
||||||
|
clear;
|
||||||
|
clc;
|
||||||
|
|
||||||
|
TimeStamp = [];
|
||||||
|
FreqCarrier = 2450e6;% 中心频点可调
|
||||||
|
Bandwidth = 5e6;% 带宽可调 20~40e6
|
||||||
|
Ts = 1/Bandwidth;
|
||||||
|
|
||||||
|
FrameNum = 1;
|
||||||
|
PacketSize = 200; %
|
||||||
|
load NumerologySet.mat NumerologySet
|
||||||
|
NumerologySel = NumerologySet(1,:); % 128 0.25 3 % N_FFT; CPratio; PilotInterval
|
||||||
|
|
||||||
|
MCS_set=[2,2;4,2;4,4;16,2;16,4;64,3;64,4;64,6];% 加密算法需要做一个适配,CHB,3.19;注释:第8个方案有问题
|
||||||
|
MCS_no = MCS_set(5,:);
|
||||||
|
|
||||||
|
% 仿真参数
|
||||||
|
Delay_set = [1:20]*Ts;
|
||||||
|
Velocity_set = [5:250];
|
||||||
|
SNR_set = [0:5:35];
|
||||||
|
|
||||||
|
SNR = 25;
|
||||||
|
tau_d = Delay_set(randi([1 20]));
|
||||||
|
velocity = Velocity_set(randi([1 length(Velocity_set)]));
|
||||||
|
|
||||||
|
ChanPara = ChanStat(SNR, tau_d, velocity, Ts, FreqCarrier, TimeStamp);
|
||||||
|
|
||||||
|
seed_set = [1 2 3];
|
||||||
|
|
||||||
|
[SysParameters,WaveformPara] = WaveformNumerologyCal(PacketSize,NumerologySel,MCS_no);
|
||||||
|
%% TX
|
||||||
|
rng(seed_set(1),'twister');
|
||||||
|
dataPacketBits = randi([0 1],WaveformPara.Payload,1);
|
||||||
|
scrData = TX_CRC32_Scramble(dataPacketBits);
|
||||||
|
trellis = poly2trellis(7,[171 133]);
|
||||||
|
tx_encoded_bit = convenc(scrData,trellis,WaveformPara.puncpat);
|
||||||
|
tx_padded_bit = [tx_encoded_bit;zeros(WaveformPara.DataPadding,1)];
|
||||||
|
%---------------------------------------------
|
||||||
|
dataMod = qammod(tx_padded_bit,WaveformPara.Mod,'InputType','bit');
|
||||||
|
WaveformPara.Power_sym = mean(abs(dataMod).^2);
|
||||||
|
dataMod = reshape(dataMod,WaveformPara.UsedSubcarrier,[]);
|
||||||
|
%% 获取信道响应 %假设已知前一时刻的信号
|
||||||
|
% 生成信道响应
|
||||||
|
N_carriers = WaveformPara.N_FFT;
|
||||||
|
channel_response=sqrt(1/2)*(randn(1,N_carriers)+1i*randn(1,N_carriers));
|
||||||
|
N_windows = 8;
|
||||||
|
N_level = 10;
|
||||||
|
min_len_CP = 30;
|
||||||
|
% 测试函数
|
||||||
|
CPset = Generate_CP(channel_response,N_windows,N_level,min_len_CP);
|
||||||
|
|
||||||
|
% 物理层加密
|
||||||
|
[serialOFDMsym,WaveformPara.pilot,serialFrameLen,symbolNum] = tx_FFTSymbolGen_PilotBlockPN(dataMod,WaveformPara,CPset); % 加CP的地方
|
||||||
|
WaveformPara.Power_sig = mean(abs(serialOFDMsym).^2);
|
||||||
|
serialOFDMsym = serialOFDMsym./max(abs(serialOFDMsym));
|
||||||
|
% [WaveformPara.preamble,WaveformPara.c1,WaveformPara.c2] = ...
|
||||||
|
% generatePreamble(WaveformPara,WaveformPara.Power_sig); % hb:这里前导码的目的是什么?
|
||||||
|
% txSignal = [WaveformPara.preamble;serialOFDMsym];
|
||||||
|
% RFSignal = RFimpairment(txSignal, FreqCarrier);
|
||||||
|
|
||||||
|
%% Parameter
|
||||||
|
NumerologyNo = 1; % 1~27
|
||||||
|
FrameNo = 7;
|
||||||
|
% MCS_No = 3;
|
||||||
|
% PacketSize = 200;
|
||||||
|
|
||||||
|
cfg = wlanNonHTConfig('SignalChannelBandwidth',true, ...
|
||||||
|
'BandwidthOperation','Static');
|
||||||
|
|
||||||
|
% cfg.MCS = MCS_No;
|
||||||
|
cfg.PSDULength = PacketSize; %0-4095
|
||||||
|
%% preamble
|
||||||
|
tx_STF = STS_modulation(NumerologyNo); % STF
|
||||||
|
tx_LTF = wlanLLTF(cfg); % LTF
|
||||||
|
[tx_SIG, tx_sigdata] = newLSIG(cfg,FrameNo);% SIG
|
||||||
|
% load('preambleData.mat')
|
||||||
|
|
||||||
|
txSignal = [tx_STF;tx_LTF;tx_SIG;serialOFDMsym];
|
||||||
|
txSignalNormalized = txSignal;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
% A = 20*log10(abs(fft(txSignal)));
|
||||||
|
% plot(A);
|
||||||
|
% 分两块,发送 接收
|
||||||
|
%% Channel
|
||||||
|
% [rxSignal,ChanPara] = PassChan(txSignal,WaveformPara,SysParameters,ChanPara,seed_set(2));
|
||||||
|
len = 20000;
|
||||||
|
n = rand(len,1)+rand(len,1)*1i;
|
||||||
|
rxSignal = [n*0.1;txSignalNormalized];
|
||||||
|
|
||||||
|
% SIR = InterfCal(rxSignal,ChanPara);
|
||||||
|
|
||||||
|
%% RX
|
||||||
|
% [rxSignal_sync,SyncErr] = rxSyncSC(rxSignal,WaveformPara,serialFrameLen);
|
||||||
|
% process preamble
|
||||||
|
[rxSignal_sync,MCS,PSDULength,failCheck,rec_frameNo,estNumerlogy,numeroError] = rx_preambleprocess(rxSignal);
|
||||||
|
rxSignal_sync = rxSignal_sync(1:serialFrameLen);
|
||||||
|
|
||||||
|
[rxDataModLs] = rx_PilotBlockChanEst(rxSignal_sync,ChanPara,WaveformPara,CPset,symbolNum,SysParameters); % 去CP的地方
|
||||||
|
dataDemod = qamdemod(rxDataModLs,WaveformPara.Mod,'OutputType','approxllr', ...
|
||||||
|
'UnitAveragePower',false,'NoiseVariance',0.0243);%ChanPara.N0
|
||||||
|
dataDePadded = dataDemod(1:end - WaveformPara.DataPadding);
|
||||||
|
tb = 8;
|
||||||
|
decoded = vitdec(dataDePadded,trellis,tb,'trunc','unquant',WaveformPara.puncpat);
|
||||||
|
|
||||||
|
[rx,PER] = RX_CRC32_deScramble(decoded); % 丢包率
|
||||||
|
[numErrors,BER] = biterr(dataPacketBits,rx);
|
||||||
|
BER
|
||||||
|
PER
|
||||||
|
% SyncErr
|
||||||
|
|
||||||
|
%%
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
42
WaveAdp/newLSIG.m
Normal file
42
WaveAdp/newLSIG.m
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
function [y, bits] = newLSIG(cfgFormat,frameNo)
|
||||||
|
|
||||||
|
R = wlan.internal.nonHTRateSignalBits(cfgFormat.MCS);
|
||||||
|
length = cfgFormat.PSDULength;
|
||||||
|
|
||||||
|
|
||||||
|
% Construct the SIGNAL field. Length parameter with LSB first, which is 12 bits
|
||||||
|
lengthBits = de2bi(length,12,'right-msb').';
|
||||||
|
|
||||||
|
% Even parity bit
|
||||||
|
parityBit = mod(sum([R;lengthBits],1),2);
|
||||||
|
|
||||||
|
% 自建:插入帧号
|
||||||
|
frameNoBits = de2bi(frameNo,6,'right-msb').';
|
||||||
|
|
||||||
|
% The SIGNAL field (IEEE Std 802.11-2016, Section 17.3.4.2)
|
||||||
|
% bits = [R; 0; lengthBits; parityBit; zeros(6,1,'int8')];
|
||||||
|
bits = [R; 0; lengthBits; parityBit; frameNoBits];
|
||||||
|
|
||||||
|
% Process L-SIG bits
|
||||||
|
encodedBits = wlanBCCEncode(bits,'1/2');
|
||||||
|
interleavedBits = wlanBCCInterleave(encodedBits,'Non-HT',48);
|
||||||
|
modData = wlanConstellationMap(interleavedBits,1);
|
||||||
|
|
||||||
|
% Add pilot symbols, from IEEE Std 802.11-2016, Equation 19-14
|
||||||
|
Nsym = 1; % One symbol
|
||||||
|
z = 0; % No offset as first symbol is with pilots
|
||||||
|
modPilots = wlan.internal.nonHTPilots(Nsym,z);
|
||||||
|
|
||||||
|
% Map subcarriers and replicate over bandwidth
|
||||||
|
cfgOFDM = wlan.internal.wlanGetOFDMConfig(cfgFormat.ChannelBandwidth,'Long','Legacy');
|
||||||
|
sym = complex(zeros(cfgOFDM.FFTLength,1));
|
||||||
|
sym(cfgOFDM.DataIndices,1) = repmat(modData,cfgOFDM.NumSubchannels,1);
|
||||||
|
sym(cfgOFDM.PilotIndices,1) = repmat(modPilots,cfgOFDM.NumSubchannels,1);
|
||||||
|
|
||||||
|
% Apply gamma rotation, replicate over antennas and apply cyclic shifts
|
||||||
|
[lsig,scalingFactor] = wlan.internal.legacyFieldMap(sym,cfgOFDM.NumTones,cfgFormat);
|
||||||
|
|
||||||
|
% OFDM modulate
|
||||||
|
y = wlan.internal.wlanOFDMModulate(lsig,cfgOFDM.CyclicPrefixLength)*scalingFactor;
|
||||||
|
|
||||||
|
end
|
BIN
WaveAdp/preambleData.mat
Normal file
BIN
WaveAdp/preambleData.mat
Normal file
Binary file not shown.
0
WaveAdp/rRemoveIFO.m
Normal file
0
WaveAdp/rRemoveIFO.m
Normal file
97
WaveAdp/rxSyncSC.m
Normal file
97
WaveAdp/rxSyncSC.m
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
function [rxSignal,SyncErr] = rxSyncSC(rxSignal,WaveformPara,myFrameLen)
|
||||||
|
SyncErr = 0;
|
||||||
|
N = WaveformPara.N_FFT;
|
||||||
|
L = WaveformPara.CP_Len;
|
||||||
|
delay = 6000;
|
||||||
|
c1 = WaveformPara.c1;
|
||||||
|
c2 = WaveformPara.c2;
|
||||||
|
preamble = WaveformPara.preamble;
|
||||||
|
|
||||||
|
timing = estSymTiming(rxSignal,N,L);%%%%%%%%%
|
||||||
|
tshift = delay+L+1-timing;
|
||||||
|
if timing > WaveformPara.CP_Len+delay
|
||||||
|
SyncErr=1;
|
||||||
|
timing = delay+1;
|
||||||
|
end
|
||||||
|
|
||||||
|
rRemoveSTO = rxSignal(timing:end);%%%%%%%%%%%%%
|
||||||
|
|
||||||
|
phi = estFFO(rRemoveSTO,N,L);%%%%%%%%%%%%
|
||||||
|
rRemoveFFO = rRemoveSTO.*exp(-sqrt(-1)*2*pi*(1:length(rRemoveSTO))'*phi/N);
|
||||||
|
|
||||||
|
gEst = estIFO(rRemoveFFO,N,L,c1,c2);%%%%%%%%%%%
|
||||||
|
|
||||||
|
rRemoveIFO = rRemoveFFO.*exp(-sqrt(-1)*2*pi*(1:length(rRemoveFFO))'*(2*gEst)/N);
|
||||||
|
|
||||||
|
fshift = phi+2*gEst;
|
||||||
|
|
||||||
|
startWindow = length(preamble)-L+1;%%%%%%%%%%%%
|
||||||
|
% endWindow = startWindow+WaveformPara.FrameLen-1;%
|
||||||
|
endWindow = startWindow+myFrameLen-1;%
|
||||||
|
rxSignal = rRemoveIFO(startWindow:endWindow);
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
%% APPENDIX
|
||||||
|
function [timing,Mavg] = estSymTiming(r,N,L)
|
||||||
|
P = zeros(length(r)-2*N/2+1,1);
|
||||||
|
R = zeros(length(r)-2*N/2+1,1);
|
||||||
|
M = zeros(length(P),1);
|
||||||
|
|
||||||
|
for d = 1:length(M)
|
||||||
|
P(d) = (r(d:d+N/2-1))'*r(d+N/2:d+N-1);
|
||||||
|
|
||||||
|
R(d) = (r(d+N/2:d+N-1))'*r(d+N/2:d+N-1);
|
||||||
|
|
||||||
|
M(d) = (abs(P(d)))^2/(R(d))^2;
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
movavgWindow = dsp.MovingAverage(L-1);
|
||||||
|
Mavg = movavgWindow(M);
|
||||||
|
Mavg = Mavg(L/2:end);
|
||||||
|
[Mmax,timing] = max(Mavg);
|
||||||
|
timing=183;
|
||||||
|
figure
|
||||||
|
plot(M)
|
||||||
|
hold on;
|
||||||
|
plot(Mavg)
|
||||||
|
end
|
||||||
|
|
||||||
|
function gEst = estIFO(rRemoveFFO,N,L,c1,c2)
|
||||||
|
X = 1:2:N-1;
|
||||||
|
|
||||||
|
v = sqrt(2)*c2(X)./c1(X);
|
||||||
|
x1 = fft(rRemoveFFO(1:N))/sqrt(N);
|
||||||
|
x2 = fft(rRemoveFFO(1+N+L:2*N+L))/sqrt(N);
|
||||||
|
|
||||||
|
D = 2*(sum((abs(x2(X))).^2))^2;
|
||||||
|
|
||||||
|
gNum = N/2;
|
||||||
|
X1 = zeros(N,gNum);
|
||||||
|
X2 = zeros(N,gNum);
|
||||||
|
X1(:,1) = x1;
|
||||||
|
X2(:,1) = x2;
|
||||||
|
|
||||||
|
for i = 2:gNum
|
||||||
|
X1(:,i) = [X1(3:end,i-1);X1(1:2,i-1)];
|
||||||
|
X2(:,i) = [X2(3:end,i-1);X2(1:2,i-1)];
|
||||||
|
end
|
||||||
|
|
||||||
|
B = zeros(gNum,1);
|
||||||
|
|
||||||
|
for i = 1:gNum
|
||||||
|
B(i) = (abs(sum(...
|
||||||
|
conj(X1(X,i)).*conj(v).*X2(X,i)...
|
||||||
|
)))^2/D;
|
||||||
|
end
|
||||||
|
|
||||||
|
[Bmax,g] = max(B);
|
||||||
|
G = [0:N/4-1,-N/4:-1];
|
||||||
|
gEst = G(g);
|
||||||
|
end
|
||||||
|
|
||||||
|
function phi = estFFO(r,N,L)
|
||||||
|
P = sum(conj(r(1:N/2)).*r(N/2+1:2*N/2));
|
||||||
|
phi = angle(P)/pi;
|
||||||
|
end
|
71
WaveAdp/rx_PilotBlockChanEstForLabview.m
Normal file
71
WaveAdp/rx_PilotBlockChanEstForLabview.m
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
|
||||||
|
function [rxDataModLs] = rx_PilotBlockChanEst(rAddAWGN,WaveformPara,CPset,SysParameters)
|
||||||
|
N = WaveformPara.N_FFT;
|
||||||
|
N_Used = WaveformPara.UsedSubcarrier;
|
||||||
|
L = WaveformPara.CP_Len;
|
||||||
|
m = WaveformPara.PilotNum;
|
||||||
|
pnSequence = comm.PNSequence('Polynomial',[8 6 5 4 0], ...
|
||||||
|
'SamplesPerFrame',WaveformPara.UsedSubcarrier,'InitialConditions',[0 0 0 0 0 0 0 1]);
|
||||||
|
WaveformPara.pilot = generatePilot(pnSequence,1);
|
||||||
|
pilot = WaveformPara.pilot;
|
||||||
|
|
||||||
|
% rxOFDMsym = reshape(rAddAWGN,WaveformPara.SymbolLen,WaveformPara.FrameSymNum);
|
||||||
|
% rxOFDMcore = rxOFDMsym(L+1:L+N,:); % 去CP的地方
|
||||||
|
|
||||||
|
rxOFDMcore = [];
|
||||||
|
% 将矩阵操作转换成对列操作
|
||||||
|
kk1=1;
|
||||||
|
for i = 1:length(CPset)
|
||||||
|
get_idx = kk1:(kk1 + N + CPset(i)-1);
|
||||||
|
currentSym = rAddAWGN(get_idx);
|
||||||
|
rxOFDMcore = [rxOFDMcore,currentSym(CPset(i)+1:end)];
|
||||||
|
kk1=kk1+(N+CPset(i));
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
rxDataModInMatrix = fft(rxOFDMcore,[],1)/sqrt(N);
|
||||||
|
|
||||||
|
rxDataModInMatrix_shift = [rxDataModInMatrix(2:2+(N_Used-1)/2-1,:);rxDataModInMatrix(end - (N_Used-1)/2:end,:)];
|
||||||
|
|
||||||
|
rxPilot = rxDataModInMatrix_shift(:,1:WaveformPara.PilotInterval+1:WaveformPara.FrameSymNum);
|
||||||
|
|
||||||
|
hLs = zeros(N_Used,m);
|
||||||
|
|
||||||
|
rxDataRemovPilot = zeros(N_Used,WaveformPara.DataFrame);
|
||||||
|
|
||||||
|
|
||||||
|
for i = 1:m-1
|
||||||
|
rxDataRemovPilot(:,(i-1)*WaveformPara.PilotInterval+1:i*(WaveformPara.PilotInterval)) = ...
|
||||||
|
rxDataModInMatrix_shift(:,(i-1)*(WaveformPara.PilotInterval+1)+2:i*(WaveformPara.PilotInterval+1));
|
||||||
|
hLs(:,i) = rxPilot(:,i)./pilot;
|
||||||
|
end
|
||||||
|
|
||||||
|
rxDataRemovPilot(:,(m-1)*WaveformPara.PilotInterval+1:end) = ...
|
||||||
|
rxDataModInMatrix_shift(:,(m-1)*(WaveformPara.PilotInterval+1)+2:end);
|
||||||
|
hLs(:,m) = rxPilot(:,m)./pilot;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if mod(WaveformPara.DataFrame,WaveformPara.PilotInterval)>0
|
||||||
|
hLs = [kron(hLs(:,1:m-1),ones(1,WaveformPara.PilotInterval)),kron(hLs(:,m),ones(1,mod(WaveformPara.DataFrame,WaveformPara.PilotInterval)))];
|
||||||
|
else
|
||||||
|
hLs = kron(hLs(:,1:m),ones(1,WaveformPara.PilotInterval));
|
||||||
|
end
|
||||||
|
|
||||||
|
eqDataModLs = zeros(N_Used,WaveformPara.DataFrame);
|
||||||
|
|
||||||
|
for i = 1:WaveformPara.DataFrame
|
||||||
|
eqDataModLs(:,i) = rxDataRemovPilot(:,i)./hLs(:,i);
|
||||||
|
end
|
||||||
|
|
||||||
|
rxDataModLs = reshape(eqDataModLs,[],1);
|
||||||
|
|
||||||
|
end
|
||||||
|
%%
|
||||||
|
function pilot = generatePilot(pnSequence,Power)
|
||||||
|
|
||||||
|
pilot = pnSequence();
|
||||||
|
|
||||||
|
bpskModulator = comm.BPSKModulator;
|
||||||
|
pilot = bpskModulator(pilot)*sqrt(Power);
|
||||||
|
end
|
80
WaveAdp/rx_PilotBlockChanEst_CPrand.m
Normal file
80
WaveAdp/rx_PilotBlockChanEst_CPrand.m
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
|
||||||
|
function [rxDataModLs] = rx_PilotBlockChanEst_CPrand(rAddAWGN,ChanPara,WaveformPara,CPset,symbolNum,SysParameters)
|
||||||
|
N = WaveformPara.N_FFT;
|
||||||
|
N_Used = WaveformPara.UsedSubcarrier;
|
||||||
|
L = WaveformPara.CP_Len;
|
||||||
|
m = WaveformPara.PilotNum;
|
||||||
|
pilot = WaveformPara.pilot;
|
||||||
|
|
||||||
|
% rxOFDMsym = reshape(rAddAWGN,WaveformPara.SymbolLen,WaveformPara.FrameSymNum);
|
||||||
|
% rxOFDMcore = rxOFDMsym(L+1:L+N,:); % 去CP的地方
|
||||||
|
|
||||||
|
rxOFDMcore = [];
|
||||||
|
% 将矩阵操作转换成对列操作
|
||||||
|
kk1=1;
|
||||||
|
lenCPset = length(CPset);
|
||||||
|
if lenCPset<symbolNum
|
||||||
|
for i = 1:symbolNum
|
||||||
|
if i <= lenCPset
|
||||||
|
get_idx = kk1:(kk1 + N + CPset(i)-1);
|
||||||
|
currentSym = rAddAWGN(get_idx);
|
||||||
|
rxOFDMcore = [rxOFDMcore,currentSym(CPset(i)+1:end)];
|
||||||
|
kk1=kk1+(N+CPset(i));
|
||||||
|
else
|
||||||
|
get_idx = kk1:(kk1 + N + CPset(end)-1);
|
||||||
|
currentSym = rAddAWGN(get_idx);
|
||||||
|
rxOFDMcore = [rxOFDMcore,currentSym(CPset(end)+1:end)];
|
||||||
|
kk1=kk1+(N+CPset(end));
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif lenCPset == symbolNum
|
||||||
|
for i = 1:symbolNum
|
||||||
|
get_idx = kk1:(kk1 + N + CPset(i)-1);
|
||||||
|
currentSym = rAddAWGN(get_idx);
|
||||||
|
rxOFDMcore = [rxOFDMcore,currentSym(CPset(i)+1:end)];
|
||||||
|
kk1=kk1+(N+CPset(i));
|
||||||
|
end
|
||||||
|
|
||||||
|
else
|
||||||
|
print('waiting for solve')
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
rxDataModInMatrix = fft(rxOFDMcore,[],1)/sqrt(N);
|
||||||
|
|
||||||
|
rxDataModInMatrix_shift = [rxDataModInMatrix(2:2+(N_Used-1)/2-1,:);rxDataModInMatrix(end - (N_Used-1)/2:end,:)];
|
||||||
|
|
||||||
|
rxPilot = rxDataModInMatrix_shift(:,1:WaveformPara.PilotInterval+1:WaveformPara.FrameSymNum);
|
||||||
|
|
||||||
|
hLs = zeros(N_Used,m);
|
||||||
|
|
||||||
|
rxDataRemovPilot = zeros(N_Used,WaveformPara.DataFrame);
|
||||||
|
|
||||||
|
|
||||||
|
for i = 1:m-1
|
||||||
|
rxDataRemovPilot(:,(i-1)*WaveformPara.PilotInterval+1:i*(WaveformPara.PilotInterval)) = ...
|
||||||
|
rxDataModInMatrix_shift(:,(i-1)*(WaveformPara.PilotInterval+1)+2:i*(WaveformPara.PilotInterval+1));
|
||||||
|
hLs(:,i) = rxPilot(:,i)./pilot;
|
||||||
|
end
|
||||||
|
|
||||||
|
rxDataRemovPilot(:,(m-1)*WaveformPara.PilotInterval+1:end) = ...
|
||||||
|
rxDataModInMatrix_shift(:,(m-1)*(WaveformPara.PilotInterval+1)+2:end);
|
||||||
|
hLs(:,m) = rxPilot(:,m)./pilot;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if mod(WaveformPara.DataFrame,WaveformPara.PilotInterval)>0
|
||||||
|
hLs = [kron(hLs(:,1:m-1),ones(1,WaveformPara.PilotInterval)),kron(hLs(:,m),ones(1,mod(WaveformPara.DataFrame,WaveformPara.PilotInterval)))];
|
||||||
|
else
|
||||||
|
hLs = kron(hLs(:,1:m),ones(1,WaveformPara.PilotInterval));
|
||||||
|
end
|
||||||
|
|
||||||
|
eqDataModLs = zeros(N_Used,WaveformPara.DataFrame);
|
||||||
|
|
||||||
|
for i = 1:WaveformPara.DataFrame
|
||||||
|
eqDataModLs(:,i) = rxDataRemovPilot(:,i)./hLs(:,i);
|
||||||
|
end
|
||||||
|
|
||||||
|
rxDataModLs = reshape(eqDataModLs,[],1);
|
||||||
|
|
||||||
|
end
|
90
WaveAdp/rx_preambleprocess.m
Normal file
90
WaveAdp/rx_preambleprocess.m
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
function [rx_datafield,MCS,PSDULength,failCheck,rec_frameNo,estNumerlogy,numeroError] = rx_preambleprocess(rx)
|
||||||
|
|
||||||
|
searchOffset = 0; % Offset from start of waveform in samples
|
||||||
|
rxWaveLen = 30000;
|
||||||
|
cfg = wlanNonHTConfig('SignalChannelBandwidth',true, ...
|
||||||
|
'BandwidthOperation','Static');
|
||||||
|
|
||||||
|
% Generate field indices
|
||||||
|
ind = wlanFieldIndices(cfg);
|
||||||
|
chanBW = cfg.ChannelBandwidth;
|
||||||
|
sr = wlanSampleRate(cfg); % Sample rate
|
||||||
|
|
||||||
|
% while (searchOffset + minPktLen) <= rxWaveLen
|
||||||
|
|
||||||
|
% Packet detection
|
||||||
|
threshold = 0.8;
|
||||||
|
|
||||||
|
[pktOffset,M] = wlanPacketDetect(rx,chanBW,searchOffset,threshold);
|
||||||
|
plot(M)
|
||||||
|
% Adjust packet offset
|
||||||
|
pktOffset = searchOffset + pktOffset;
|
||||||
|
if isempty(pktOffset) || (pktOffset + ind.LSIG(2) > rxWaveLen)
|
||||||
|
error('** No packet detected **');
|
||||||
|
end
|
||||||
|
% Coarse frequency offset estimation and correction using L-STF
|
||||||
|
rxLSTF = rx(pktOffset+(ind.LSTF(1):ind.LSTF(2)), :);
|
||||||
|
coarseFreqOffset = wlanCoarseCFOEstimate(rxLSTF,chanBW);
|
||||||
|
rx = helperFrequencyOffset(rx,sr,-coarseFreqOffset);
|
||||||
|
% Symbol timing synchronization
|
||||||
|
searchBufferLLTF = rx(pktOffset+(ind.LSTF(1):ind.LSIG(2)),:);
|
||||||
|
pktOffset = pktOffset+wlanSymbolTimingEstimate(searchBufferLLTF,chanBW);
|
||||||
|
% Fine frequency offset estimation and correction using L-STF
|
||||||
|
rxLLTF = rx(pktOffset+(ind.LLTF(1):ind.LLTF(2)),:);
|
||||||
|
|
||||||
|
fineFreqOffset = wlanFineCFOEstimate(rxLLTF,chanBW);
|
||||||
|
rx = helperFrequencyOffset(rx,sr,-fineFreqOffset);
|
||||||
|
|
||||||
|
% Scale the waveform based on L-STF power (AGC)
|
||||||
|
gain = 1./(sqrt(mean(rxLSTF.*conj(rxLSTF))));
|
||||||
|
rx = rx.*gain;
|
||||||
|
|
||||||
|
% Packet Format Detection
|
||||||
|
rxLLTF = rx(pktOffset+(ind.LLTF(1):ind.LLTF(2)),:);
|
||||||
|
lltfDemod = wlanLLTFDemodulate(rxLLTF,chanBW);
|
||||||
|
lltfChanEst = wlanLLTFChannelEstimate(lltfDemod,chanBW);
|
||||||
|
noiseVar = helperNoiseEstimate(lltfDemod);
|
||||||
|
|
||||||
|
% Recover L-SIG field bits
|
||||||
|
[rxLSIGBits, failCheck, ~] = wlanLSIGRecover(rx(pktOffset + (ind.LSIG(1):ind.LSIG(2)), :), lltfChanEst, noiseVar, chanBW);
|
||||||
|
[MCS,PSDULength] = interpretLSIG(rxLSIGBits);
|
||||||
|
rec_frameNo = bi2de(rxLSIGBits(19:24).','right-msb');
|
||||||
|
|
||||||
|
if failCheck % Skip L-STF length of samples and continue searching
|
||||||
|
disp('** L-SIG check fail **');
|
||||||
|
else
|
||||||
|
disp('L-SIG check pass');
|
||||||
|
end
|
||||||
|
|
||||||
|
% Recover Numerology field bits
|
||||||
|
rxLSTF = rx(pktOffset+(ind.LSTF(1):ind.LSTF(2)), :);
|
||||||
|
[estNumerlogy,numeroError] = STS_demod(rxLSTF);
|
||||||
|
if numeroError
|
||||||
|
disp('** Numerology check fail **');
|
||||||
|
else
|
||||||
|
disp('Numerology check pass');
|
||||||
|
end
|
||||||
|
|
||||||
|
% output data field
|
||||||
|
% rx_datafield = rx(pktOffset+(ind.NonHTData(1):ind.NonHTData(2)), :);
|
||||||
|
rx_datafield = rx(pktOffset+ind.NonHTData(1):end, :);
|
||||||
|
end
|
||||||
|
%%
|
||||||
|
function [MCS,PSDULength] = interpretLSIG(recLSIGBits)
|
||||||
|
% InterpretLSIG Interprets recovered L-SIG bits
|
||||||
|
%
|
||||||
|
% [MCS,PSDULENGTH] = interpretLSIG(RECLSIGBITS) returns the
|
||||||
|
% modulation and coding scheme and PSDU length given the recovered L-SIG
|
||||||
|
% bits
|
||||||
|
|
||||||
|
% Rate and length are determined from bits
|
||||||
|
rate = double(recLSIGBits(1:3));
|
||||||
|
length = double(recLSIGBits(5+(1:12)));
|
||||||
|
|
||||||
|
% MCS rate table, IEEE Std 802.11-2016, Table 17-6.
|
||||||
|
R = wlan.internal.nonHTRateSignalBits();
|
||||||
|
mcstmp = find(all(bsxfun(@eq,R(1:3,:),rate)))-1;
|
||||||
|
MCS = mcstmp(1); % For codegen
|
||||||
|
PSDULength = bi2de(length.');
|
||||||
|
|
||||||
|
end
|
BIN
WaveAdp/rxdata1.mat
Normal file
BIN
WaveAdp/rxdata1.mat
Normal file
Binary file not shown.
BIN
WaveAdp/rxdata2.mat
Normal file
BIN
WaveAdp/rxdata2.mat
Normal file
Binary file not shown.
BIN
WaveAdp/rxdata3preamble.mat
Normal file
BIN
WaveAdp/rxdata3preamble.mat
Normal file
Binary file not shown.
BIN
WaveAdp/rxdata4preamble.mat
Normal file
BIN
WaveAdp/rxdata4preamble.mat
Normal file
Binary file not shown.
BIN
WaveAdp/rxdata5normalized.mat
Normal file
BIN
WaveAdp/rxdata5normalized.mat
Normal file
Binary file not shown.
BIN
WaveAdp/rxdata6normalizedzero.mat
Normal file
BIN
WaveAdp/rxdata6normalizedzero.mat
Normal file
Binary file not shown.
14
WaveAdp/temp.m
Normal file
14
WaveAdp/temp.m
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
cfgNonHT = wlanNonHTConfig;
|
||||||
|
|
||||||
|
txWaveform = wlanWaveformGenerator([1;0;0;1],cfgNonHT,...
|
||||||
|
'WindowTransitionTime',0);
|
||||||
|
len = 30000;
|
||||||
|
n = rand(len,1)+rand(len,1)*1i;
|
||||||
|
rxWaveform = [n;txWaveform];
|
||||||
|
% 0.001*rand(100,1)
|
||||||
|
|
||||||
|
offset = 5;
|
||||||
|
threshold = 1-10*eps;
|
||||||
|
startOffset = wlanPacketDetect(rxWaveform,...
|
||||||
|
cfgNonHT.ChannelBandwidth,offset,threshold) ;
|
||||||
|
totalOffset = offset + startOffset
|
BIN
WaveAdp/testInputDataForLabview.mat
Normal file
BIN
WaveAdp/testInputDataForLabview.mat
Normal file
Binary file not shown.
BIN
WaveAdp/txSignalForNormalized.mat
Normal file
BIN
WaveAdp/txSignalForNormalized.mat
Normal file
Binary file not shown.
BIN
WaveAdp/txSignalForNormalizedZero.mat
Normal file
BIN
WaveAdp/txSignalForNormalizedZero.mat
Normal file
Binary file not shown.
BIN
WaveAdp/txSignalForPreamble.mat
Normal file
BIN
WaveAdp/txSignalForPreamble.mat
Normal file
Binary file not shown.
BIN
WaveAdp/txSignalForPreamble1.mat
Normal file
BIN
WaveAdp/txSignalForPreamble1.mat
Normal file
Binary file not shown.
69
WaveAdp/tx_FFTSymbolGen_PilotBlockPN_CPrand.m
Normal file
69
WaveAdp/tx_FFTSymbolGen_PilotBlockPN_CPrand.m
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
function [serialOFDMsym,pilot,serialFrameLen,symbolNum] = tx_FFTSymbolGen_PilotBlockPN_CPrand(dataModInMatrix,WaveformPara,CPset,SysParameters)
|
||||||
|
|
||||||
|
numOfdmSymbol = WaveformPara.FrameSymNum;
|
||||||
|
N_used = WaveformPara.UsedSubcarrier;
|
||||||
|
CP_Len = WaveformPara.CP_Len;
|
||||||
|
|
||||||
|
pnSequence = comm.PNSequence('Polynomial',[8 6 5 4 0], ...
|
||||||
|
'SamplesPerFrame',N_used,'InitialConditions',[0 0 0 0 0 0 0 1]);
|
||||||
|
|
||||||
|
pilotPower = WaveformPara.Power_sym;
|
||||||
|
pilot = generatePilot(pnSequence,pilotPower);
|
||||||
|
|
||||||
|
m = WaveformPara.PilotNum-1;
|
||||||
|
dataModAddPilot = zeros(N_used,numOfdmSymbol);
|
||||||
|
for i = 1:m
|
||||||
|
dataModAddPilot(:,(i-1)*(WaveformPara.PilotInterval+1)+1:i*(WaveformPara.PilotInterval+1)) = ...
|
||||||
|
[pilot,dataModInMatrix(:,(i-1)*WaveformPara.PilotInterval+1:i*WaveformPara.PilotInterval)];
|
||||||
|
end
|
||||||
|
dataModAddPilot(:,m*(WaveformPara.PilotInterval+1)+1:end) = ...
|
||||||
|
[pilot,dataModInMatrix(:,m*WaveformPara.PilotInterval+1:end)];
|
||||||
|
|
||||||
|
dataModAddPilot_shift = [zeros(1,WaveformPara.FrameSymNum);...
|
||||||
|
dataModAddPilot(1:(N_used-1)/2,:);...
|
||||||
|
zeros(WaveformPara.NullSubcarrier,WaveformPara.FrameSymNum);...
|
||||||
|
dataModAddPilot(1+(N_used-1)/2:end,:)];
|
||||||
|
|
||||||
|
|
||||||
|
OFDMsym = ifft(dataModAddPilot_shift,[],1)*sqrt(WaveformPara.N_FFT);
|
||||||
|
|
||||||
|
[~,symNum]=size(OFDMsym);
|
||||||
|
serialOFDMsym = [];
|
||||||
|
lenCPset = length(CPset);
|
||||||
|
% 对列操作
|
||||||
|
if lenCPset<symNum
|
||||||
|
for i = 1:symNum
|
||||||
|
if i <= lenCPset
|
||||||
|
serialOFDMsym = [serialOFDMsym; OFDMsym(WaveformPara.N_FFT-CPset(i)+1:end,i); OFDMsym(:,i)];
|
||||||
|
else
|
||||||
|
serialOFDMsym = [serialOFDMsym; OFDMsym(WaveformPara.N_FFT-CPset(end)+1:end,i); OFDMsym(:,i)];
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
elseif length(CPset) == symNum
|
||||||
|
for i = 1:symNum
|
||||||
|
serialOFDMsym = [serialOFDMsym; OFDMsym(WaveformPara.N_FFT-CPset(i)+1:end,i); OFDMsym(:,i)];
|
||||||
|
end
|
||||||
|
else
|
||||||
|
print('waiting for solve')
|
||||||
|
end
|
||||||
|
|
||||||
|
symbolNum = symNum;
|
||||||
|
serialFrameLen = length(serialOFDMsym);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
% OFDMsymAddCP = [OFDMsym(WaveformPara.N_FFT-CP_Len+1:end,:);OFDMsym]; % 加CP的地方
|
||||||
|
%
|
||||||
|
% serialOFDMsym = reshape(OFDMsymAddCP,[],1);
|
||||||
|
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
function pilot = generatePilot(pnSequence,Power)
|
||||||
|
|
||||||
|
pilot = pnSequence();
|
||||||
|
|
||||||
|
bpskModulator = comm.BPSKModulator;
|
||||||
|
pilot = bpskModulator(pilot)*sqrt(Power);
|
||||||
|
end
|
7
WaveAdp/说明.txt
Normal file
7
WaveAdp/说明.txt
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
纯仿真信道的代码:
|
||||||
|
mainForLabview
|
||||||
|
|
||||||
|
结合labview的代码:
|
||||||
|
TX、RX使用的是滑动窗口的方法进行同步的;
|
||||||
|
TX_forPreamble、RX_forPreamble使用的是802.11a的方法进行同步的。
|
||||||
|
|
223
bit2int.m
Normal file
223
bit2int.m
Normal file
@ -0,0 +1,223 @@
|
|||||||
|
function y = bit2int(x, N, varargin)
|
||||||
|
%BIT2INT Convert bits to integers
|
||||||
|
%
|
||||||
|
% Y = BIT2INT(X,N) converts N column-wise bit elements in X to
|
||||||
|
% nonnegative integer values, with the first or the top-most bit
|
||||||
|
% being the MSB (most significant bit). X can be a column vector,
|
||||||
|
% matrix or an array with 3 dimensions. Number of rows in X must be
|
||||||
|
% an integer multiple of N. Y has same dimensions as X, except that
|
||||||
|
% the number of rows in Y are N times less than the number of rows in
|
||||||
|
% X. The datatype of X can be any of the built-in numeric types or
|
||||||
|
% logical. When the datatype of X is -
|
||||||
|
% - double or logical, datatype of Y is double.
|
||||||
|
% - single, datatype of Y is single.
|
||||||
|
% - a built-in integer type, Y has the same datatype as X unless the
|
||||||
|
% values in Y cannot be represented in that datatype without loss of
|
||||||
|
% data. If values in Y are larger than the intmax of the datatype of
|
||||||
|
% X, then Y is of the smallest datatype that can fit the values
|
||||||
|
% without loss of data. The datatype of Y has same signedness as that
|
||||||
|
% of X.
|
||||||
|
% - double or logical, N must be no larger than 53.
|
||||||
|
% - single, N must be no larger than 24.
|
||||||
|
% - a built-in signed integer type, N must be no larger than 63.
|
||||||
|
% - a built-in unsigned integer type, N must be no larger than 64.
|
||||||
|
%
|
||||||
|
% Y = BIT2INT(X,N,MSBFIRST) specifies MSB orientation in MSBFIRST.
|
||||||
|
% When MSBFIRST is true, the first bit in each set of N column-wise
|
||||||
|
% bits in X is the MSB; when MSBFIRST is false, the first bit in each
|
||||||
|
% set of N column-wise bits in X is the LSB (least significant bit).
|
||||||
|
%
|
||||||
|
% Y = BIT2INT(___,IsSigned=TF) specifies TF as a logical which can be
|
||||||
|
% either true or false to indicate the signed-ness of the integer.
|
||||||
|
% Default is false. When TF is true, then the first bit in each block
|
||||||
|
% of N bits is considered to be a signed bit and the output may
|
||||||
|
% contain negative values. If the datatype of X is any of the
|
||||||
|
% unsigned integer types with TF set to true, then the datatype of Y
|
||||||
|
% is the smallest signed integer type that can support the number of
|
||||||
|
% input bits.
|
||||||
|
%
|
||||||
|
% Examples:
|
||||||
|
%
|
||||||
|
% A1 = [1 0 1 0 1 0 1 0]';
|
||||||
|
% N1 = 8;
|
||||||
|
% B1 = bit2int(A1, N1);
|
||||||
|
%
|
||||||
|
% A2 = int8([1 1 0; 0 1 1]');
|
||||||
|
% N2 = 3;
|
||||||
|
% msbFirst = false;
|
||||||
|
% B2 = bit2int(A2, N2, msbFirst);
|
||||||
|
%
|
||||||
|
% A3 = randi([0,1], 32, 2, 2, 'uint8');
|
||||||
|
% N3 = 16;
|
||||||
|
% B3 = bit2int(A3, N3);
|
||||||
|
%
|
||||||
|
% A4 = [-110, 103, -103, 99];
|
||||||
|
% C4 = int2bit(A4,8);
|
||||||
|
% B4 = bit2int(C4,8,IsSigned=true);
|
||||||
|
%
|
||||||
|
% See also INT2BIT.
|
||||||
|
|
||||||
|
% Copyright 2021-2022 The MathWorks, Inc.
|
||||||
|
|
||||||
|
%#codegen
|
||||||
|
narginchk(2,5);
|
||||||
|
validateattributes(x, {'numeric','logical'}, {'3d','nonempty','binary'}, '', 'X');
|
||||||
|
if nargin == 2
|
||||||
|
MSBFirst = true;
|
||||||
|
IsSigned = false;
|
||||||
|
elseif nargin == 3
|
||||||
|
% If 3 inputs, then third argument must be MSBFirst option
|
||||||
|
IsSigned = false;
|
||||||
|
MSBFirst = varargin{1};
|
||||||
|
validateattributes(MSBFirst, {'logical','numeric'}, {'scalar','binary'}, '', 'MSBFirst');
|
||||||
|
else
|
||||||
|
% Then either 4 inputs with name-value is possible or 5 inputs with
|
||||||
|
% MSBFirst option and name-value of IsSigned is possible
|
||||||
|
if nargin == 4
|
||||||
|
signedOption = {varargin{1:2}}; % Codegen does not support cellarray(...). So use curly braces
|
||||||
|
MSBFirst = true;
|
||||||
|
else % nargin == 5
|
||||||
|
MSBFirst = varargin{1};
|
||||||
|
signedOption = {varargin{2:3}};
|
||||||
|
validateattributes(MSBFirst, {'logical','numeric'}, {'scalar','binary'}, '', 'MSBFirst');
|
||||||
|
end
|
||||||
|
|
||||||
|
defaults = struct("IsSigned",false);
|
||||||
|
res = comm.internal.utilities.nvParser(defaults, signedOption{:});
|
||||||
|
IsSigned = res.IsSigned;
|
||||||
|
validateattributes(IsSigned, {'logical','numeric'}, {'scalar','binary'}, '', 'IsSigned');
|
||||||
|
end
|
||||||
|
|
||||||
|
isSim = comm.internal.utilities.isSim();
|
||||||
|
if ~isSim
|
||||||
|
coder.internal.prefer_const(N);
|
||||||
|
end
|
||||||
|
isInputLogical = islogical(x);
|
||||||
|
|
||||||
|
% When N is equal to the max int supported (for example, N==8 for
|
||||||
|
% int8), -2^N calculation gives us -2^N + 1 because first 2^N gets
|
||||||
|
% calculated which cannot be fit into its native integer type (for
|
||||||
|
% example, int8 for N=8). To handle this corner case, subtract one
|
||||||
|
% after calculating negative value.
|
||||||
|
subone = false;
|
||||||
|
|
||||||
|
if isfloat(x) || isInputLogical
|
||||||
|
if isa(x, 'single')
|
||||||
|
maxN = 24;
|
||||||
|
else
|
||||||
|
maxN = 53;
|
||||||
|
end
|
||||||
|
|
||||||
|
validateattributes(N, {'numeric'}, {'scalar','positive','integer','<=',maxN}, '', 'N');
|
||||||
|
if isInputLogical
|
||||||
|
xNew = double(x);
|
||||||
|
isInputFloat = false;
|
||||||
|
else
|
||||||
|
xNew = x;
|
||||||
|
isInputFloat = true;
|
||||||
|
end
|
||||||
|
prototype = xNew(1);
|
||||||
|
else
|
||||||
|
% built-in integers
|
||||||
|
bitClass = class(x);
|
||||||
|
if bitClass(1) == 'u'
|
||||||
|
maxN = 64;
|
||||||
|
else
|
||||||
|
maxN = 63;
|
||||||
|
end
|
||||||
|
validateattributes(N, {'numeric'}, {'scalar','positive','integer','<=',maxN}, '', 'N');
|
||||||
|
coder.internal.errorIf(~isSim && ~coder.internal.isConst(N), ...
|
||||||
|
'comm:bit2int:NNotConst');
|
||||||
|
if bitClass(1) == 'u' && IsSigned
|
||||||
|
bitClassMax = intmax(bitClass(2:end));
|
||||||
|
else
|
||||||
|
bitClassMax = intmax(bitClass);
|
||||||
|
end
|
||||||
|
|
||||||
|
if IsSigned
|
||||||
|
c = '';
|
||||||
|
else
|
||||||
|
c = 'u';
|
||||||
|
end
|
||||||
|
|
||||||
|
if bitClass(1) == 'u' || IsSigned
|
||||||
|
if N <= 8
|
||||||
|
typeMax = intmax([c 'int8']);
|
||||||
|
subone = N==8;
|
||||||
|
elseif N <= 16
|
||||||
|
typeMax = intmax([c 'int16']);
|
||||||
|
subone = N==16;
|
||||||
|
elseif N <= 32
|
||||||
|
typeMax = intmax([c 'int32']);
|
||||||
|
subone = N==32;
|
||||||
|
else
|
||||||
|
typeMax = intmax([c 'int64']);
|
||||||
|
subone = N==64;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if N <= 7
|
||||||
|
typeMax = intmax('int8');
|
||||||
|
elseif N <= 15
|
||||||
|
typeMax = intmax('int16');
|
||||||
|
elseif N <= 31
|
||||||
|
typeMax = intmax('int32');
|
||||||
|
else
|
||||||
|
typeMax = intmax('int64');
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if bitClassMax > typeMax
|
||||||
|
prototype = bitClassMax;
|
||||||
|
subone = false;
|
||||||
|
else
|
||||||
|
prototype = typeMax;
|
||||||
|
end
|
||||||
|
xNew = x;
|
||||||
|
isInputFloat = false;
|
||||||
|
end
|
||||||
|
useN = cast(N,'like',prototype);
|
||||||
|
|
||||||
|
if isInputFloat || (isSim && isInputLogical)
|
||||||
|
|
||||||
|
inSize = size(xNew);
|
||||||
|
nIntsPerCol = inSize(1)/double(N);
|
||||||
|
coder.internal.errorIf(nIntsPerCol ~= floor(nIntsPerCol), 'comm:bit2int:InvalidInputDims');
|
||||||
|
outSize = inSize;
|
||||||
|
outSize(1) = nIntsPerCol;
|
||||||
|
xMat = reshape(xNew, useN, []);
|
||||||
|
if MSBFirst
|
||||||
|
powOf2 = pow2(useN-1:-1:0);
|
||||||
|
powOf2(1) = (1-2*IsSigned)*powOf2(1);
|
||||||
|
else
|
||||||
|
powOf2 = pow2(0:useN-1);
|
||||||
|
powOf2(end) = (1-2*IsSigned)*powOf2(end);
|
||||||
|
end
|
||||||
|
|
||||||
|
y = reshape(powOf2 * xMat, outSize);
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
Nidx = coder.internal.indexInt(useN);
|
||||||
|
[nRows,nCols,nPages] = size(xNew);
|
||||||
|
nIntsPerCol = idivide(nRows, Nidx);
|
||||||
|
coder.internal.errorIf(Nidx*nIntsPerCol ~= nRows, ...
|
||||||
|
'comm:bit2int:InvalidInputDims');
|
||||||
|
|
||||||
|
y = coder.nullcopy(zeros(nIntsPerCol, nCols, nPages, 'like', prototype));
|
||||||
|
|
||||||
|
powOf2 = cast(2, 'like', y) .^ (useN-1:-1:0)';
|
||||||
|
powOf2(1) = (1-2*IsSigned)*powOf2(1)-1*subone*IsSigned;
|
||||||
|
xTmp = cast(xNew, 'like', y);
|
||||||
|
nInts = nIntsPerCol * coder.internal.indexInt(nCols) * coder.internal.indexInt(nPages);
|
||||||
|
if MSBFirst
|
||||||
|
idx = 1:Nidx;
|
||||||
|
else
|
||||||
|
idx = Nidx:-1:1;
|
||||||
|
end
|
||||||
|
for k=1:nInts
|
||||||
|
bits = xTmp(Nidx*(k-1) + idx);
|
||||||
|
y(k) = sum(bits(:) .* powOf2, 'native');
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
4
calculate_CDF.m
Normal file
4
calculate_CDF.m
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
function [CDF] = calculate_CDF(data,PAPR_bin)
|
||||||
|
count = hist(data,PAPR_bin);
|
||||||
|
CDF = cumsum(count)/sum(count);
|
||||||
|
end
|
8
calculate_PAPR.m
Normal file
8
calculate_PAPR.m
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
function [PAPR_dex,Mean_Power] = calculate_PAPR(x)
|
||||||
|
% PAPR_dex 计算得到所有符号各自的PAPR
|
||||||
|
% Mean_Power 符号的平均功率
|
||||||
|
Signal_Power = abs(x).^2;
|
||||||
|
Peak_Power = max(Signal_Power,[],1); % norm(x,Inf)^2
|
||||||
|
Mean_Power = mean(Signal_Power,1); % norm(x,2)^2/(K*IF)
|
||||||
|
PAPR_dex = Peak_Power./Mean_Power;
|
||||||
|
end
|
28
channelSounding.m
Normal file
28
channelSounding.m
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
function txNDP = channelSounding(cfg)
|
||||||
|
% 产生NDP
|
||||||
|
guardInterval = 0.8;% Guard interval in Microseconds
|
||||||
|
cfgNDP = wlanHESUConfig('APEPLength',0,'GuardInterval',guardInterval); % No data in an NDP
|
||||||
|
cfgNDP.ChannelBandwidth = cfg.ChannelBandwidth;
|
||||||
|
cfgNDP.NumTransmitAntennas = cfg.numTx;
|
||||||
|
cfgNDP.NumSpaceTimeStreams = cfg.numTx;
|
||||||
|
txNDP = wlanWaveformGenerator([],cfgNDP);
|
||||||
|
|
||||||
|
% 加入PN序列,正交序列,重复三次左右
|
||||||
|
soundingSeqMod_1 = zadoffChuSeq(29,255);
|
||||||
|
soundingSeqMod_2 = zadoffChuSeq(47,255);
|
||||||
|
|
||||||
|
% Concatenate multiple sequences to sound the channel periodically.
|
||||||
|
numSeq = 20; % Number of transmitted sequences in a WSS period
|
||||||
|
if cfg.numTx == 1
|
||||||
|
soundingSeqMod = [soundingSeqMod_1];
|
||||||
|
txSignal = repmat(soundingSeqMod,numSeq,1);
|
||||||
|
else
|
||||||
|
soundingSeqMod = [soundingSeqMod_1, soundingSeqMod_2];
|
||||||
|
txSignal = repmat(soundingSeqMod,numSeq,1);
|
||||||
|
end
|
||||||
|
|
||||||
|
% with 50 sample padding.
|
||||||
|
% txNDP = [txNDP; zeros(50,size(txNDP,2))];
|
||||||
|
txNDP = [txNDP; txSignal; zeros(50,size(txNDP,2))];
|
||||||
|
|
||||||
|
end
|
18
createMUMIMO.m
Normal file
18
createMUMIMO.m
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
function cfgMUMIMO = createMUMIMO(Tx, CP, NumSpaceTimeStreams, MCS, APEPLength, numUsers)
|
||||||
|
numTx = Tx; % Number of transmit antennas
|
||||||
|
% MU-MIMO configuration - 4 users on one 242-tone RU
|
||||||
|
cfgMUMIMO = wlanHEMUConfig(191+numUsers);
|
||||||
|
|
||||||
|
guardInterval = CP; % Guard interval in Microseconds
|
||||||
|
|
||||||
|
% Configure common parameters for all users
|
||||||
|
cfgMUMIMO.NumTransmitAntennas = numTx;
|
||||||
|
cfgMUMIMO.GuardInterval = guardInterval;
|
||||||
|
|
||||||
|
% Configure per user parameters
|
||||||
|
for idx = 1:numUsers
|
||||||
|
cfgMUMIMO.User{idx}.NumSpaceTimeStreams = NumSpaceTimeStreams(idx);
|
||||||
|
cfgMUMIMO.User{idx}.MCS = MCS(idx);
|
||||||
|
cfgMUMIMO.User{idx}.APEPLength = APEPLength(idx);
|
||||||
|
end
|
||||||
|
end
|
219
demodSIG.m
Normal file
219
demodSIG.m
Normal file
@ -0,0 +1,219 @@
|
|||||||
|
%% 解包头
|
||||||
|
function [cfgRx,cfgUsers,rmsEVM,failCRC] = demodSIG(rx,rx_format,cfgUI)%% Packet Format Detection
|
||||||
|
%% L-LTF Channel Estimate
|
||||||
|
% Demodulate the L-LTF and perform channel estimation. The demodulated
|
||||||
|
% L-LTF symbols include tone rotation for each 20 MHz segment as described
|
||||||
|
% in [ <#16 2> ], section 21.3.7.5. The L-LTF channel estimates (with tone
|
||||||
|
% rotation) are used to equalize and decode the pre-HE-LTF fields.
|
||||||
|
|
||||||
|
lltfDemod = wlanHEDemodulate(rxLLTF,'L-LTF',chanBW);
|
||||||
|
lltfChanEst = wlanLLTFChannelEstimate(lltfDemod,chanBW);
|
||||||
|
|
||||||
|
%% L-SIG and RL-SIG Decoding
|
||||||
|
% The L-SIG field is used to determine the receive time, or RXTIME, of the
|
||||||
|
% packet. The RXTIME is calculated using the length bits of the L-SIG
|
||||||
|
% payload. The L-SIG and RL-SIG fields are recovered to perform the channel
|
||||||
|
% estimate on the extra subcarriers in the L-SIG and RL-SIG fields. The
|
||||||
|
% |lltfChanEst| channel estimates are updated to include the channel
|
||||||
|
% estimates on extra subcarriers in the L-SIG and RL-SIG fields. The L-SIG
|
||||||
|
% payload is decoded using an estimate of the channel and noise power
|
||||||
|
% obtained from the L-LTF field. The L-SIG length property in
|
||||||
|
% <matlab:edit('wlanHERecoveryConfig.m') wlanHERecoveryConfig> is updated after L-SIG decoding.
|
||||||
|
|
||||||
|
disp('Decoding L-SIG... ');
|
||||||
|
% Extract L-SIG and RL-SIG fields
|
||||||
|
rxLSIG = rx(pktOffset+(ind.LSIG(1):ind.RLSIG(2)),:);
|
||||||
|
|
||||||
|
% OFDM demodulate
|
||||||
|
helsigDemod = wlanHEDemodulate(rxLSIG,'L-SIG',chanBW);
|
||||||
|
|
||||||
|
% Estimate CPE and phase correct symbols
|
||||||
|
helsigDemod = preHECommonPhaseErrorTracking(helsigDemod,lltfChanEst,'L-SIG',chanBW);
|
||||||
|
|
||||||
|
% Estimate channel on extra 4 subcarriers per subchannel and create full
|
||||||
|
% channel estimate
|
||||||
|
preheInfo = wlanHEOFDMInfo('L-SIG',chanBW);
|
||||||
|
preHEChanEst = preHEChannelEstimate(helsigDemod,lltfChanEst,preheInfo.NumSubchannels);
|
||||||
|
|
||||||
|
% Average L-SIG and RL-SIG before equalization
|
||||||
|
helsigDemod = mean(helsigDemod,2);
|
||||||
|
|
||||||
|
% Equalize data carrying subcarriers, merging 20 MHz subchannels
|
||||||
|
[eqLSIGSym,csi] = preHESymbolEqualize(helsigDemod(preheInfo.DataIndices,:,:), ...
|
||||||
|
preHEChanEst(preheInfo.DataIndices,:,:),noiseVar,preheInfo.NumSubchannels);
|
||||||
|
|
||||||
|
% Decode L-SIG field
|
||||||
|
[~,failCheck,lsigInfo] = wlanLSIGBitRecover(eqLSIGSym,noiseVar,csi);
|
||||||
|
|
||||||
|
if failCheck
|
||||||
|
disp(' ** L-SIG check fail **');
|
||||||
|
else
|
||||||
|
disp(' L-SIG check pass');
|
||||||
|
end
|
||||||
|
% Get the length information from the recovered L-SIG bits and update the
|
||||||
|
% L-SIG length property of the recovery configuration object
|
||||||
|
lsigLength = lsigInfo.Length;
|
||||||
|
cfgRx.LSIGLength = lsigLength;
|
||||||
|
|
||||||
|
% Measure EVM of L-SIG symbols
|
||||||
|
EVM = comm.EVM;
|
||||||
|
EVM.ReferenceSignalSource = 'Estimated from reference constellation';
|
||||||
|
EVM.Normalization = 'Average constellation power';
|
||||||
|
EVM.ReferenceConstellation = wlanReferenceSymbols('BPSK');
|
||||||
|
rmsEVM = EVM(eqLSIGSym);
|
||||||
|
fprintf(' L-SIG EVM: %2.2fdB\n\n',20*log10(rmsEVM/100));
|
||||||
|
|
||||||
|
% Calculate the receive time and corresponding number of samples in the
|
||||||
|
% packet
|
||||||
|
RXTime = ceil((lsigLength + 3)/3) * 4 + 20; % In microseconds
|
||||||
|
numRxSamples = round(RXTime * 1e-6 * sr); % Number of samples in time
|
||||||
|
|
||||||
|
fprintf(' RXTIME: %dus\n',RXTime);
|
||||||
|
fprintf(' Number of samples in the packet: %d\n\n',numRxSamples);
|
||||||
|
|
||||||
|
%%
|
||||||
|
% The waveform and spectrum of the detected packet within |rx| is
|
||||||
|
% displayed given the calculated RXTIME and corresponding number of
|
||||||
|
% samples.
|
||||||
|
|
||||||
|
sampleOffset = max((-lstfLength + pktOffset),1); % First index to plot
|
||||||
|
sampleSpan = numRxSamples + 2*lstfLength; % Number samples to plot
|
||||||
|
% Plot as much of the packet (and extra samples) as we can
|
||||||
|
plotIdx = sampleOffset:min(sampleOffset + sampleSpan,rxWaveLen);
|
||||||
|
|
||||||
|
% Configure timeScope to display the packet 展示
|
||||||
|
timeScope.TimeSpan = sampleSpan/sr;
|
||||||
|
timeScope.TimeDisplayOffset = sampleOffset/sr;
|
||||||
|
timeScope.YLimits = [0 max(abs(rx(:)))];
|
||||||
|
timeScope(abs(rx(plotIdx,:)));
|
||||||
|
release(timeScope);
|
||||||
|
|
||||||
|
% Display the spectrum of the detected packet 展示
|
||||||
|
spectrumAnalyzer(rx(pktOffset + (1:numRxSamples),:));
|
||||||
|
release(spectrumAnalyzer);
|
||||||
|
|
||||||
|
%% HE-SIG-A Decoding
|
||||||
|
% The HE-SIG-A field contains the transmission configuration of an HE
|
||||||
|
% packet. An estimate of the channel and noise power obtained from the
|
||||||
|
% L-LTF is required to decode the HE-SIG-A field.
|
||||||
|
|
||||||
|
disp('Decoding HE-SIG-A...')
|
||||||
|
rxSIGA = rx(pktOffset+(ind.HESIGA(1):ind.HESIGA(2)),:);
|
||||||
|
sigaDemod = wlanHEDemodulate(rxSIGA,'HE-SIG-A',chanBW);
|
||||||
|
hesigaDemod = preHECommonPhaseErrorTracking(sigaDemod,preHEChanEst,'HE-SIG-A',chanBW);
|
||||||
|
|
||||||
|
% Equalize data carrying subcarriers, merging 20 MHz subchannels
|
||||||
|
preheInfo = wlanHEOFDMInfo('HE-SIG-A',chanBW);
|
||||||
|
[eqSIGASym,csi] = preHESymbolEqualize(hesigaDemod(preheInfo.DataIndices,:,:), ...
|
||||||
|
preHEChanEst(preheInfo.DataIndices,:,:), ...
|
||||||
|
noiseVar,preheInfo.NumSubchannels);
|
||||||
|
% Recover HE-SIG-A bits
|
||||||
|
[sigaBits,failCRC] = wlanHESIGABitRecover(eqSIGASym,noiseVar,csi);
|
||||||
|
|
||||||
|
% Perform the CRC on HE-SIG-A bits
|
||||||
|
if failCRC
|
||||||
|
disp(' ** HE-SIG-A CRC fail **');
|
||||||
|
else
|
||||||
|
disp(' HE-SIG-A CRC pass');
|
||||||
|
end
|
||||||
|
|
||||||
|
% Measure EVM of HE-SIG-A symbols
|
||||||
|
release(EVM);
|
||||||
|
if strcmp(pktFormat,'HE-EXT-SU')
|
||||||
|
% The second symbol of an HE-SIG-A field for an HE-EXT-SU packet is
|
||||||
|
% QBPSK.
|
||||||
|
EVM.ReferenceConstellation = wlanReferenceSymbols('BPSK',[0 pi/2 0 0]);
|
||||||
|
% Account for scaling of L-LTF for an HE-EXT-SU packet
|
||||||
|
rmsEVM = EVM(eqSIGASym*sqrt(2));
|
||||||
|
else
|
||||||
|
EVM.ReferenceConstellation = wlanReferenceSymbols('BPSK');
|
||||||
|
rmsEVM = EVM(eqSIGASym);
|
||||||
|
end
|
||||||
|
fprintf(' HE-SIG-A EVM: %2.2fdB\n\n',20*log10(mean(rmsEVM)/100));
|
||||||
|
|
||||||
|
%% Interpret Recovered HE-SIG-A bits
|
||||||
|
% The <matlab:edit('wlanHERecoveryConfig.m') wlanHERecoveryConfig> object
|
||||||
|
% is updated after interpreting the recovered HE-SIG-A bits.
|
||||||
|
|
||||||
|
cfgRx = interpretHESIGABits(cfgRx,sigaBits);
|
||||||
|
ind = wlanFieldIndices(cfgRx); % Update field indices
|
||||||
|
%%
|
||||||
|
% Display the common transmission configuration obtained from HE-SIG-A
|
||||||
|
% field for an HE-MU packet. The properties indicated by -1 are unknown or
|
||||||
|
% undefined. The unknown user-related properties are updated after
|
||||||
|
% successful decoding of the HE-SIG-B field.
|
||||||
|
disp(cfgRx)
|
||||||
|
|
||||||
|
%% HE-SIG-B Decoding
|
||||||
|
% For an HE-MU packet the HE-SIG-B field contains:
|
||||||
|
%
|
||||||
|
% * The RU allocation information for a non-compressed SIGB waveform is
|
||||||
|
% inferred from HE-SIG-B Common field [ <#16 1> Table. 27-23]. For a
|
||||||
|
% compressed SIGB waveform the RU allocation information is inferred from
|
||||||
|
% the recovered HE-SIG-A bits.
|
||||||
|
% * For a non-compressed SIGB waveform the number of HE-SIG-B symbols are
|
||||||
|
% updated in the <matlab:edit('wlanHERecoveryConfig.m') wlanHERecoveryConfig> object.
|
||||||
|
% The symbols are only updated if the number of HE-SIG-B symbols indicated
|
||||||
|
% in the HE-SIG-A field is set to 15 and all content channels pass the CRC.
|
||||||
|
% The number of HE-SIG-B symbols indicated in the HE-SIG-A field are not
|
||||||
|
% updated if any HE-SIG-B content channel fails the CRC.
|
||||||
|
% * The user transmission parameters for both SIGB compressed and
|
||||||
|
% non-compressed waveforms are inferred from the HE-SIG-B user field [ <#16 1>
|
||||||
|
% Table. 27-25, 27-26].
|
||||||
|
%
|
||||||
|
% An estimate of the channel and noise power obtained from the L-LTF is
|
||||||
|
% required to decode the HE-SIG-B field.
|
||||||
|
|
||||||
|
if strcmp(pktFormat,'HE-MU')
|
||||||
|
fprintf('Decoding HE-SIG-B...\n');
|
||||||
|
if ~cfgRx.SIGBCompression
|
||||||
|
fprintf(' Decoding HE-SIG-B common field...\n');
|
||||||
|
s = getSIGBLength(cfgRx);
|
||||||
|
% Get common field symbols. The start of HE-SIG-B field is known
|
||||||
|
rxSym = rx(pktOffset+(ind.HESIGA(2)+(1:s.NumSIGBCommonFieldSamples)),:);
|
||||||
|
% Decode HE-SIG-B common field
|
||||||
|
[status,cfgRx] = heSIGBCommonFieldDecode(rxSym,preHEChanEst,noiseVar,cfgRx);
|
||||||
|
|
||||||
|
% CRC on HE-SIG-B content channels
|
||||||
|
if strcmp(status,'Success')
|
||||||
|
fprintf(' HE-SIG-B (common field) CRC pass\n');
|
||||||
|
elseif strcmp(status,'ContentChannel1CRCFail')
|
||||||
|
fprintf(' ** HE-SIG-B CRC fail for content channel-1\n **');
|
||||||
|
elseif strcmp(status,'ContentChannel2CRCFail')
|
||||||
|
fprintf(' ** HE-SIG-B CRC fail for content channel-2\n **');
|
||||||
|
elseif any(strcmp(status,{'UnknownNumUsersContentChannel1','UnknownNumUsersContentChannel2'}))
|
||||||
|
error(' ** Unknown packet length, discard packet\n **');
|
||||||
|
else
|
||||||
|
% Discard the packet if all HE-SIG-B content channels fail
|
||||||
|
error(' ** HE-SIG-B CRC fail **');
|
||||||
|
end
|
||||||
|
% Update field indices as the number of HE-SIG-B symbols are
|
||||||
|
% updated
|
||||||
|
ind = wlanFieldIndices(cfgRx);
|
||||||
|
end
|
||||||
|
|
||||||
|
% Get complete HE-SIG-B field samples
|
||||||
|
rxSIGB = rx(pktOffset+(ind.HESIGB(1):ind.HESIGB(2)),:);
|
||||||
|
fprintf(' Decoding HE-SIG-B user field... \n');
|
||||||
|
% Decode HE-SIG-B user field
|
||||||
|
[failCRC,cfgUsers] = heSIGBUserFieldDecode(rxSIGB,preHEChanEst,noiseVar,cfgRx);
|
||||||
|
|
||||||
|
% CRC on HE-SIG-B users
|
||||||
|
if ~all(failCRC)
|
||||||
|
fprintf(' HE-SIG-B (user field) CRC pass\n\n');
|
||||||
|
numUsers = numel(cfgUsers);
|
||||||
|
elseif all(failCRC)
|
||||||
|
% Discard the packet if all users fail the CRC
|
||||||
|
error(' ** HE-SIG-B CRC fail for all users **');
|
||||||
|
else
|
||||||
|
fprintf(' ** HE-SIG-B CRC fail for at least one user\n **');
|
||||||
|
% Only process users with valid CRC
|
||||||
|
numUsers = numel(cfgUsers);
|
||||||
|
end
|
||||||
|
|
||||||
|
else % HE-SU, HE-EXT-SU
|
||||||
|
cfgUsers = {cfgRx};
|
||||||
|
numUsers = 1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
6
findPDF.m
Normal file
6
findPDF.m
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
function pdf = findPDF(range,data)
|
||||||
|
pdf = zeros(length(range)-1,1);
|
||||||
|
for i = 1:length(range)-1
|
||||||
|
pdf(i) = length(find(range(i) < data & data <= range(i+1)))/length(data);
|
||||||
|
end
|
||||||
|
end
|
4
findTemporalParameters.m
Normal file
4
findTemporalParameters.m
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
function [delay_average,delay_spread]=findTemporalParameters(PDP, T_sample, K)
|
||||||
|
delay_average = sum(PDP.*(0:K-1).'*T_sample)/sum(PDP);
|
||||||
|
delay_spread = sqrt(sum(PDP.*((0:K-1).'*T_sample-delay_average).^2)/sum(PDP));
|
||||||
|
end
|
32
heCPECorrection.m
Normal file
32
heCPECorrection.m
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
function rx = heCPECorrection(rx,sigbPilots,chanEst,chanBW)
|
||||||
|
%heCPECorrection Estimate and correct common phase error
|
||||||
|
%
|
||||||
|
% RX = heCPECorrection(RX,SIGBPILOTS,CHANEST,CHANBW) returns the phase
|
||||||
|
% corrected OFDM symbols of HE-SIG-B field using the input, RX, HE-SIG-B
|
||||||
|
% pilot symbols, SIGBPILOTS, channel estimates, CHANEST, and channel
|
||||||
|
% bandwidth CHANBW.
|
||||||
|
%
|
||||||
|
% RX is a complex Nst-by-Nsym-by-Nr array containing the received OFDM
|
||||||
|
% symbols. Nst is the number of subcarriers and Nr is the number of
|
||||||
|
% receive antennas.
|
||||||
|
%
|
||||||
|
% SIGBPILOTS are the pilots symbols in the demodulated HE-SIG-B field.
|
||||||
|
%
|
||||||
|
% CHANEST is a complex Nst-by-1-by-Nr array containing the estimated
|
||||||
|
% channel at data and pilot subcarriers, where Nst is the number of
|
||||||
|
% occupied subcarriers and Nr is the number of receive antennas.
|
||||||
|
%
|
||||||
|
% CHANBW is a character vector or string. The allowed channel bandwidth
|
||||||
|
% are 'CBW20', 'CBW40', 'CBW80' and 'CBW160'.
|
||||||
|
|
||||||
|
% Copyright 2018 The MathWorks, Inc.
|
||||||
|
|
||||||
|
numSubchannels = wlan.internal.cbwStr2Num(chanBW)/20;
|
||||||
|
|
||||||
|
numBits = size(sigbPilots,2);
|
||||||
|
z = 4;
|
||||||
|
refPilots = repmat(wlan.internal.nonHTPilots(numBits, z),numSubchannels,1,1);
|
||||||
|
cpe = wlan.internal.commonPhaseErrorEstimate(sigbPilots,chanEst,refPilots);
|
||||||
|
rx = wlan.internal.commonPhaseErrorCorrect(rx,cpe);
|
||||||
|
|
||||||
|
end
|
92
heCommonPhaseErrorTracking.m
Normal file
92
heCommonPhaseErrorTracking.m
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
function [y,cpe] = heCommonPhaseErrorTracking(x,chanEst,cfg,varargin)
|
||||||
|
%heCommonPhaseErrorTracking HE common pilot phase tracking
|
||||||
|
%
|
||||||
|
% [Y,CPE] = heCommonPhaseErrorTracking(X,CHANEST,CFGHE) performs common
|
||||||
|
% pilot error phase tracking of the single user HE format input X.
|
||||||
|
%
|
||||||
|
% Y is a complex Nst-by-Nsym-by-Nr array containing the common phase
|
||||||
|
% corrected OFDM symbols. Nst is the number of occupied subcarriers, Nsym
|
||||||
|
% is the number of symbols, and Nr is the number of receive antennas. Y
|
||||||
|
% is the common phase error corrected symbols.
|
||||||
|
%
|
||||||
|
% X is a complex Nst-by-Nsym-by-Nr array containing the received OFDM
|
||||||
|
% symbols.
|
||||||
|
%
|
||||||
|
% CHANEST is a complex Nst-by-Nsts-by-Nr array containing the channel
|
||||||
|
% gains for all active subcarriers, or a Nsp-by-Nsts-by-Nr array
|
||||||
|
% containing the channel gains for only pilot subcarriers. Nsts is the
|
||||||
|
% number of space-time streams.
|
||||||
|
%
|
||||||
|
% CFGHE is the format configuration object of type <a href="matlab:help('wlanHESUConfig')">wlanHESUConfig</a>,
|
||||||
|
% <a href="matlab:help('wlanHETBConfig')">wlanHETBConfig</a> or <a href="matlab:help('wlanHERecoveryConfig')">wlanHERecoveryConfig</a>.
|
||||||
|
%
|
||||||
|
% [Y,CPE] = heCommonPhaseErrorTracking(X,CHANEST,CFGMU,RUNUMBER) performs
|
||||||
|
% common pilot error phase tracking of the multi-user HE format input X.
|
||||||
|
%
|
||||||
|
% CFGMU is the format configuration object of type <a href="matlab:help('wlanHEMUConfig')">wlanHEMUConfig</a>.
|
||||||
|
%
|
||||||
|
% RUNUMBER is the RU (resource unit) number.
|
||||||
|
|
||||||
|
% Copyright 2017-2019 The MathWorks, Inc.
|
||||||
|
|
||||||
|
%#codegen
|
||||||
|
|
||||||
|
validateattributes(cfg,{'wlanHESUConfig','wlanHEMUConfig','wlanHETBConfig','wlanHERecoveryConfig'},{'scalar'},mfilename,'format configuration object');
|
||||||
|
|
||||||
|
if isa(cfg,'wlanHERecoveryConfig')
|
||||||
|
pktFormat = cfg.PacketFormat;
|
||||||
|
if strcmp(pktFormat,'HE-MU')
|
||||||
|
numSpaceTimeStreamsPerRU = cfg.RUTotalSpaceTimeStreams;
|
||||||
|
s = getSIGBLength(cfg);
|
||||||
|
numHESIGB = s.NumSIGBSymbols;
|
||||||
|
else % SU or EXT_SU
|
||||||
|
numSpaceTimeStreamsPerRU = cfg.NumSpaceTimeStreams;
|
||||||
|
numHESIGB = 0;
|
||||||
|
end
|
||||||
|
ruIdx = cfg.RUIndex;
|
||||||
|
ruSize = cfg.RUSize;
|
||||||
|
else % wlanHESUConfig,wlanHEMUConfig,wlanHETBConfig
|
||||||
|
pktFormat = packetFormat(cfg);
|
||||||
|
allocInfo = ruInfo(cfg);
|
||||||
|
if strcmp(pktFormat,'HE-MU')
|
||||||
|
narginchk(4,4)
|
||||||
|
ruNumber = varargin{1};
|
||||||
|
sigbInfo = wlan.internal.heSIGBCodingInfo(cfg);
|
||||||
|
numHESIGB = sigbInfo.NumSymbols;
|
||||||
|
numSpaceTimeStreamsPerRU = allocInfo.NumSpaceTimeStreamsPerRU(ruNumber);
|
||||||
|
ruSize = allocInfo.RUSizes(ruNumber);
|
||||||
|
ruIdx = allocInfo.RUIndices(ruNumber);
|
||||||
|
else
|
||||||
|
% SU, EXT SU, TB
|
||||||
|
numHESIGB = 0;
|
||||||
|
ruIdx = allocInfo.RUIndices;
|
||||||
|
numSpaceTimeStreamsPerRU = allocInfo.NumSpaceTimeStreamsPerRU;
|
||||||
|
ruSize = allocInfo.RUSizes;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
numOFDMSym = size(x,2);
|
||||||
|
n = (0:numOFDMSym-1);
|
||||||
|
if strcmp(pktFormat,'HE-EXT-SU')
|
||||||
|
numHESIGA = 4;
|
||||||
|
else % SU or MU
|
||||||
|
numHESIGA = 2;
|
||||||
|
end
|
||||||
|
|
||||||
|
z = 2+numHESIGA+numHESIGB; % Pilot symbol offset
|
||||||
|
refPilots = wlan.internal.hePilots(ruSize,numSpaceTimeStreamsPerRU,n,z);
|
||||||
|
|
||||||
|
% Estimate CPE and phase correct symbols
|
||||||
|
info = wlanHEOFDMInfo('HE-Data',cfg.ChannelBandwidth,cfg.GuardInterval,[ruSize ruIdx]);
|
||||||
|
|
||||||
|
if numel(info.PilotIndices)==size(chanEst,1)
|
||||||
|
% Assume channel estimate is only for pilots
|
||||||
|
chanEstPilots = chanEst;
|
||||||
|
else
|
||||||
|
% Otherwise extract pilots from channel estimate
|
||||||
|
chanEstPilots = chanEst(info.PilotIndices,:,:);
|
||||||
|
end
|
||||||
|
cpe = wlan.internal.commonPhaseErrorEstimate(x(info.PilotIndices,:,:),chanEstPilots,refPilots);
|
||||||
|
y = wlan.internal.commonPhaseErrorCorrect(x,cpe);
|
||||||
|
|
||||||
|
end
|
78
heEqualizeCombine.m
Normal file
78
heEqualizeCombine.m
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
function [y,csi] = heEqualizeCombine(x,chanEst,nVar,cfg,varargin)
|
||||||
|
%heEqualizeCombine HE MIMO channel equalization and STBC combining
|
||||||
|
%
|
||||||
|
% [Y,CSI] = heEqualizeCombine(X,CHANEST,NOISEVAR,CFGHE) performs
|
||||||
|
% minimum-mean-square-error (MMSE) frequency domain equalization and
|
||||||
|
% optionally STBC combining using the signal input X, the channel
|
||||||
|
% estimate, CHANEST, and noise variance, NVAR.
|
||||||
|
%
|
||||||
|
% Y is an estimate of the transmitted frequency domain signal and is of
|
||||||
|
% size Nsd-by-Nsym-by-Nsts, where Nsd represents the number of carriers
|
||||||
|
% (frequency domain), Nsym represents the number of symbols (time
|
||||||
|
% domain), and Nsts represents the number of space-time streams (spatial
|
||||||
|
% domain). It is complex when either X or CHANEST is complex, or is real
|
||||||
|
% otherwise.
|
||||||
|
%
|
||||||
|
% CSI is a real matrix of size Nsd-by-Nsts containing the soft channel
|
||||||
|
% state information.
|
||||||
|
%
|
||||||
|
% X is a real or complex array containing the frequency domain signal to
|
||||||
|
% equalize. It is of size Nsd-by-Nsym-by-Nr, where Nr represents the
|
||||||
|
% number of receive antennas.
|
||||||
|
%
|
||||||
|
% CHANEST is a real or complex array containing the channel estimates for
|
||||||
|
% each carrier and symbol. It is of size Nsd-by-Nsts-by-Nr.
|
||||||
|
%
|
||||||
|
% NVAR is a nonnegative scalar representing the noise variance.
|
||||||
|
%
|
||||||
|
% CFGHE is the format configuration object of type <a href="matlab:help('wlanHESUConfig')">wlanHESUConfig</a>,
|
||||||
|
% <a href="matlab:help('wlanHETBConfig')">wlanHETBConfig</a> or <a href="matlab:help('wlanHERecoveryConfig')">wlanHERecoveryConfig</a>.
|
||||||
|
%
|
||||||
|
% [Y,CSI] = heEqualizeCombine(X,CHANEST,NVAR,CFGMU,USERIDX) performs
|
||||||
|
% equalization of a HE multi user transmission. The user index is
|
||||||
|
% required to extract the space-time streams of interest for the user.
|
||||||
|
%
|
||||||
|
% CFGMU is the format configuration object of type <a href="matlab:help('wlanHEMUConfig')">wlanHEMUConfig</a> or,
|
||||||
|
% <a href="matlab:help('heTBSystemConfig')">heTBSystemConfig</a>, which specifies the parameters for multi user
|
||||||
|
% HE format and trigger-based (HT TB) system format configuration object
|
||||||
|
% respectively.
|
||||||
|
%
|
||||||
|
% USERIDX is the index of the user to decode within the RU.
|
||||||
|
|
||||||
|
% Copyright 2017-2019 The MathWorks, Inc.
|
||||||
|
|
||||||
|
%#codegen
|
||||||
|
|
||||||
|
validateattributes(cfg,{'wlanHESUConfig','wlanHEMUConfig','wlanHETBConfig','heTBSystemConfig','wlanHERecoveryConfig'},{'scalar'},mfilename,'format configuration object');
|
||||||
|
|
||||||
|
% Defaults
|
||||||
|
userIdx = 1;
|
||||||
|
if isa(cfg,'wlanHEMUConfig')
|
||||||
|
narginchk(5,5) % Require user index for multi-user reception
|
||||||
|
if nargin>4
|
||||||
|
userIdx = varargin{1};
|
||||||
|
end
|
||||||
|
% Get the indices of the space-time streams for this user
|
||||||
|
allSTSIdx = wlan.internal.heSpaceTimeStreamIndices(cfg);
|
||||||
|
stsIdx = allSTSIdx(1,userIdx):allSTSIdx(2,userIdx);
|
||||||
|
elseif isa(cfg,'wlanHERecoveryConfig') && strcmp(cfg.PacketFormat,'HE-MU')
|
||||||
|
% Get the indices of the space-time streams for this user
|
||||||
|
stsIdx = cfg.SpaceTimeStreamStartingIndex:(cfg.SpaceTimeStreamStartingIndex+cfg.NumSpaceTimeStreams-1);
|
||||||
|
else
|
||||||
|
stsIdx = 1; % For codegen
|
||||||
|
end
|
||||||
|
|
||||||
|
if cfg.STBC
|
||||||
|
% Only SU, get num of SS from size of channel estimate
|
||||||
|
nss = size(chanEst,2)/2;
|
||||||
|
[y,csi] = wlan.internal.wlanSTBCCombine(x,chanEst,nss,'MMSE',nVar);
|
||||||
|
else
|
||||||
|
% Equalize
|
||||||
|
[y,csi] = helperSymbolEqualize(x,chanEst,nVar);
|
||||||
|
if isa(cfg,'wlanHEMUConfig') || (isa(cfg,'wlanHERecoveryConfig') && strcmp(cfg.PacketFormat,'HE-MU'))
|
||||||
|
% Extract used STS
|
||||||
|
y = y(:,:,stsIdx);
|
||||||
|
csi = csi(:,stsIdx);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
281
heLTFChannelEstimate.m
Normal file
281
heLTFChannelEstimate.m
Normal file
@ -0,0 +1,281 @@
|
|||||||
|
function [chanEstRU,varargout] = heLTFChannelEstimate(demodHELTFRU,cfg,varargin)
|
||||||
|
%heLTFChannelEstimate Channel estimation using HE-LTF
|
||||||
|
% CHANESTRU = heLTFChannelEstimate(RXSYM,CFGHE) returns the estimated
|
||||||
|
% channel between all space-time streams and receive antennas using
|
||||||
|
% HE-LTF of an HE single user, extended range single user, multi-user or
|
||||||
|
% trigger-based (HE TB) packet. The channel estimate includes the
|
||||||
|
% effect of the applied spatial mapping matrix and cyclic shifts at the
|
||||||
|
% transmitter. If HE-LTF compression is used, linear interpolation is
|
||||||
|
% performed to create a channel estimate for all subcarriers.
|
||||||
|
%
|
||||||
|
% CHANESTRU is an array characterizing the estimated channel for the data
|
||||||
|
% and pilot subcarriers. EST is a complex Nst-by-Nsts-by-Nr array
|
||||||
|
% characterizing the estimated channel for the data and pilot
|
||||||
|
% subcarriers, where Nst is the number of occupied subcarriers, Nsts is
|
||||||
|
% the total number of space-time streams, and Nr is the number of receive
|
||||||
|
% antennas. If CFGHE is a MU configuration, then the channel estimate for
|
||||||
|
% all RUs is returned.
|
||||||
|
%
|
||||||
|
% RXSYM is a complex Nst-by-Nsym-by-Nr array containing demodulated
|
||||||
|
% concatenated HE-LTF. Nsym is the number of demodulated HE-LTF symbols.
|
||||||
|
%
|
||||||
|
% CFGHE is a format configuration object of type <a href="matlab:help('wlanHESUConfig')">wlanHESUConfig</a>
|
||||||
|
% <a href="matlab:help('wlanHEMUConfig')">wlanHEMUConfig</a>, <a href="matlab:help('wlanHETBConfig')">wlanHETBConfig</a>, <a href="matlab:help('heTBSystemConfig')">heTBSystemConfig</a> or <a href="matlab:help('wlanHERecoveryConfig')">wlanHERecoveryConfig</a>.
|
||||||
|
%
|
||||||
|
% CHANESTRU = heLTFChannelEstimate(RXSYM,CFGMU,RUOFINTEREST) returns the
|
||||||
|
% channel estimate for the RU of interest index RUOFINTEREST for a
|
||||||
|
% multi-user configuration. CFGMU is of type <a href="matlab:help('wlanHEMUConfig')">wlanHEMUConfig</a> or
|
||||||
|
% <a href="matlab:help('heTBSystemConfig')">heTBSystemConfig</a>. If not provided the default is 1.
|
||||||
|
%
|
||||||
|
% [...,CHANESTSSPILOTS] = heLTFChannelEstimate(...) additionally returns
|
||||||
|
% a Nsp-by-Nsym-by-Nr array characterizing the estimated channel for
|
||||||
|
% pilot subcarrier locations for each symbol, assuming one space-time
|
||||||
|
% stream at the transmitter.
|
||||||
|
%
|
||||||
|
% Examples:
|
||||||
|
% % Decode the HE data field for each user in and OFDMA and MU-MIMO
|
||||||
|
% % transmission with a fading channel model. Estimate the channel for
|
||||||
|
% % each user.
|
||||||
|
%
|
||||||
|
% % Create packet configuration
|
||||||
|
% allocationIndex = [192 193]; % Two 242 RUs, the second with 2 users
|
||||||
|
% cfg = wlanHEMUConfig(allocationIndex);
|
||||||
|
% cfg.NumTransmitAntennas = 2;
|
||||||
|
% cfg.User{1}.NumSpaceTimeStreams = 2;
|
||||||
|
%
|
||||||
|
% % Generate MU waveform
|
||||||
|
% txWaveform = wlanWaveformGenerator([1;0;0;1],cfg);
|
||||||
|
%
|
||||||
|
% % Channel and receiver per user
|
||||||
|
% ind = wlanFieldIndices(cfg);
|
||||||
|
% allocationInfo = ruInfo(cfg);
|
||||||
|
% for ruIdx = 1:allocationInfo.NumRUs
|
||||||
|
% for userIdx = 1:allocationInfo.NumUsersPerRU(ruIdx)
|
||||||
|
% % Add channel and noise
|
||||||
|
% snr = 20;
|
||||||
|
% channel = wlanTGaxChannel;
|
||||||
|
% channel.NumTransmitAntennas = 2;
|
||||||
|
% channel.NumReceiveAntennas = 2;
|
||||||
|
% channel.SampleRate = wlanSampleRate(cfg);
|
||||||
|
% rxWaveform = awgn(channel([txWaveform; zeros(10,2)]),snr);
|
||||||
|
%
|
||||||
|
% % Synchronize
|
||||||
|
% rxWaveform = rxWaveform(1+4:end,:);
|
||||||
|
%
|
||||||
|
% % Extract and OFDM demodulate the HE-LTF for the RU of
|
||||||
|
% % interest
|
||||||
|
% rxHETLF = rxWaveform(ind.HELTF(1): ind.HELTF(2),:);
|
||||||
|
% demodHELTF = wlanHEDemodulate(rxHETLF,'HE-LTF',cfg,ruIdx);
|
||||||
|
%
|
||||||
|
% % Channel estimate for RU of interest
|
||||||
|
% chanEst = heLTFChannelEstimate(demodHELTF,cfg,ruIdx);
|
||||||
|
%
|
||||||
|
% % Extract and OFDM demodulate the data field for the RU of
|
||||||
|
% % interest
|
||||||
|
% rxData = rxWaveform(ind.HEData(1):ind.HEData(2),:);
|
||||||
|
% demodData = wlanHEDemodulate(rxData,'HE-Data',cfg,ruIdx);
|
||||||
|
%
|
||||||
|
% % Equalize data symbols - extract the space-time streams for
|
||||||
|
% % the user of interest after equalization
|
||||||
|
% nVar = 10^-(snr/10);
|
||||||
|
% [eqSym,csi] = heEqualizeCombine(demodData,chanEst,nVar, ...
|
||||||
|
% cfg,userIdx);
|
||||||
|
%
|
||||||
|
% % Discard pilot carriers and decode
|
||||||
|
% info = wlanHEOFDMInfo('HE-Data',cfg,ruIdx);
|
||||||
|
% rxBits = wlanHEDataBitRecover(eqSym(info.DataIndices,:,:), ...
|
||||||
|
% nVar,csi(info.DataIndices,:),cfg,userIdx);
|
||||||
|
% end
|
||||||
|
% end
|
||||||
|
|
||||||
|
% Copyright 2017-2019 The MathWorks, Inc.
|
||||||
|
|
||||||
|
%#codegen
|
||||||
|
|
||||||
|
if nargin>2
|
||||||
|
ruOfInterest = varargin{1};
|
||||||
|
else
|
||||||
|
ruOfInterest = 1;
|
||||||
|
end
|
||||||
|
|
||||||
|
% Validate the format configuration object is a valid type
|
||||||
|
validateattributes(cfg,{'wlanHESUConfig','wlanHEMUConfig','wlanHETBConfig','heTBSystemConfig','wlanHERecoveryConfig'},{'scalar'},mfilename,'format configuration object');
|
||||||
|
|
||||||
|
% Get allocation information
|
||||||
|
if isa(cfg,'wlanHERecoveryConfig')
|
||||||
|
ruSizeRU = cfg.RUSize;
|
||||||
|
ruIndexRU = cfg.RUIndex;
|
||||||
|
pktFormat = cfg.PacketFormat;
|
||||||
|
if strcmp(pktFormat,'HE-MU')
|
||||||
|
numSTSRU = cfg.RUTotalSpaceTimeStreams;
|
||||||
|
else % SU, EXT SU
|
||||||
|
numSTSRU = cfg.NumSpaceTimeStreams;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
allocInfo = ruInfo(cfg);
|
||||||
|
coder.internal.errorIf(ruOfInterest>allocInfo.NumRUs,'wlan:he:InvalidRUOfInterest',ruOfInterest,allocInfo.NumRUs);
|
||||||
|
ruSizeRU = allocInfo.RUSizes(ruOfInterest);
|
||||||
|
ruIndexRU = allocInfo.RUIndices(ruOfInterest);
|
||||||
|
numSTSRU = allocInfo.NumSpaceTimeStreamsPerRU(ruOfInterest);
|
||||||
|
pktFormat = packetFormat(cfg);
|
||||||
|
end
|
||||||
|
|
||||||
|
% Validate symbol type
|
||||||
|
validateattributes(demodHELTFRU,{'single','double'},{'3d'},mfilename,'HE-LTF OFDM symbol(s)');
|
||||||
|
[numST,numLTF,numRx] = size(demodHELTFRU);
|
||||||
|
tac = wlan.internal.heRUToneAllocationConstants(ruSizeRU);
|
||||||
|
coder.internal.errorIf(numST~=tac.NST,'wlan:wlanChannelEstimate:IncorrectNumSC',tac.NST,numST);
|
||||||
|
ofdmInfo = wlanHEOFDMInfo('HE-LTF',cfg.ChannelBandwidth,cfg.GuardInterval,[ruSizeRU ruIndexRU]);
|
||||||
|
if numLTF==0
|
||||||
|
chanEstRU = zeros(numST,numSTSRU,numRx);
|
||||||
|
varargout{1} = zeros(numel(ofdmInfo.PilotIndices),numLTF,numRx); % For codegen
|
||||||
|
return;
|
||||||
|
end
|
||||||
|
minNumLTF = wlan.internal.numVHTLTFSymbols(numSTSRU);
|
||||||
|
coder.internal.errorIf(numLTF<minNumLTF,'wlan:he:InvalidNumLTF',numLTF,minNumLTF);
|
||||||
|
|
||||||
|
% Get the HE-LTF sequence
|
||||||
|
cbw = wlan.internal.cbwStr2Num(cfg.ChannelBandwidth);
|
||||||
|
[HELTF,kHELTFSeq] = wlan.internal.heLTFSequence(cbw,cfg.HELTFType);
|
||||||
|
|
||||||
|
% Extract the RU of interest from the full-bandwidth HELTF
|
||||||
|
kRU = ofdmInfo.ActiveFrequencyIndices;
|
||||||
|
[~,ruIdx] = intersect(kHELTFSeq,kRU);
|
||||||
|
HELTFRU = HELTF(ruIdx);
|
||||||
|
|
||||||
|
switch cfg.HELTFType
|
||||||
|
% IEEE P802.11ax/D4.1, Equation 27-52
|
||||||
|
case 1
|
||||||
|
N_HE_LTF_Mode = 4; % undefined
|
||||||
|
case 2
|
||||||
|
N_HE_LTF_Mode = 2;
|
||||||
|
otherwise % 4
|
||||||
|
N_HE_LTF_Mode = 1;
|
||||||
|
end
|
||||||
|
|
||||||
|
isaTBConfig = isa(cfg,'heTBSystemConfig') || isa(cfg,'wlanHETBConfig');
|
||||||
|
if numSTSRU==1
|
||||||
|
% Single STS
|
||||||
|
|
||||||
|
% When more than one LTF we can average over the LTFs for data and
|
||||||
|
% pilots to improve the estimate. As there is only one space-time
|
||||||
|
% stream, the pilots and data essentially both use the P matrix which
|
||||||
|
% does not change per space-time stream (only per symbol), therefore
|
||||||
|
% this "MIMO" estimate performs the averaging of the number of symbols.
|
||||||
|
chanEstRU = wlan.internal.mimoChannelEstimate(demodHELTFRU,HELTFRU,numSTSRU);
|
||||||
|
|
||||||
|
% Remove orthogonal sequence across subcarriers (if used)
|
||||||
|
if isaTBConfig && cfg.SingleStreamPilots==false
|
||||||
|
chanEstRU = removeOrthogonalSequence(chanEstRU,numSTSRU,kRU,N_HE_LTF_Mode);
|
||||||
|
end
|
||||||
|
|
||||||
|
% Interpolate if HE-LTF compression used
|
||||||
|
if N_HE_LTF_Mode>1
|
||||||
|
chanEstRU = chanEstInterp(chanEstRU,cbw,N_HE_LTF_Mode,ruSizeRU,ruIndexRU);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
% MIMO channel estimation as per Perahia, Eldad, and Robert Stacey.
|
||||||
|
% Next Generation Wireless LANs: 802.11 n and 802.11 ac. Cambridge
|
||||||
|
% University Press, 2013, page 100, Equation 4.39.
|
||||||
|
% Remove orthogonal sequence across subcarriers (if used)
|
||||||
|
if isaTBConfig && cfg.SingleStreamPilots==false
|
||||||
|
% Only perform channel estimate for non-pilot subcarriers as pilots
|
||||||
|
% are single stream
|
||||||
|
kMIMO = kRU; % All subcarriers MIMO estimates
|
||||||
|
mimoInd = 1:numST;
|
||||||
|
chanEstRUMIMO = wlan.internal.mimoChannelEstimate(demodHELTFRU,HELTFRU,numSTSRU);
|
||||||
|
chanEstRUMIMO = removeOrthogonalSequence(chanEstRUMIMO,numSTSRU,kRU,N_HE_LTF_Mode);
|
||||||
|
else
|
||||||
|
% Only perform channel estimate for non-pilot subcarriers as pilots
|
||||||
|
% are single stream
|
||||||
|
mimoInd = ofdmInfo.DataIndices;
|
||||||
|
kMIMO = kRU(mimoInd); % Only data subcarriers MIMO estimates
|
||||||
|
chanEstRUMIMO = wlan.internal.mimoChannelEstimate(demodHELTFRU(ofdmInfo.DataIndices,:,:),HELTFRU(mimoInd),numSTSRU);
|
||||||
|
end
|
||||||
|
|
||||||
|
% Undo cyclic shift for each STS before averaging and interpolation
|
||||||
|
nfft = (cbw/20)*256;
|
||||||
|
numSTSTotal = size(chanEstRUMIMO,2);
|
||||||
|
csh = wlan.internal.getCyclicShiftVal('VHT',numSTSTotal,cbw);
|
||||||
|
chanEstRUMIMO = wlan.internal.cyclicShiftChannelEstimate(chanEstRUMIMO,-csh,nfft,kMIMO);
|
||||||
|
|
||||||
|
% Interpolate over pilot locations, and any compressed subcarriers
|
||||||
|
chanEstRU = chanEstInterp(chanEstRUMIMO,cbw,N_HE_LTF_Mode,ruSizeRU,ruIndexRU,mimoInd);
|
||||||
|
|
||||||
|
% Re-apply cyclic shift after interpolation
|
||||||
|
chanEstRU = wlan.internal.cyclicShiftChannelEstimate(chanEstRU,csh,nfft,kRU);
|
||||||
|
end
|
||||||
|
|
||||||
|
% If extended range SU, then the HE-LTF are boosted by sqrt(2). If we
|
||||||
|
% don't remove this at demodulation then we must de-scale the channel
|
||||||
|
% estimate as the data field is not scaled.
|
||||||
|
if strcmp(pktFormat,'HE-EXT-SU')
|
||||||
|
eta = 1/sqrt(2);
|
||||||
|
else
|
||||||
|
eta = 1;
|
||||||
|
end
|
||||||
|
chanEstRU = chanEstRU*eta; % Scale for HE-EXT-SU
|
||||||
|
|
||||||
|
% Channel estimate for pilots
|
||||||
|
if nargout>1
|
||||||
|
if isaTBConfig && cfg.SingleStreamPilots==false
|
||||||
|
% Create single stream from MIMO pilot estimates by summing across
|
||||||
|
% space-time streams (2nd dimension)
|
||||||
|
varargout{1} = sum(chanEstRU(ofdmInfo.PilotIndices,:,:),2);
|
||||||
|
else
|
||||||
|
% Channel estimate for single-stream pilots
|
||||||
|
Pheltf = wlan.internal.mappingMatrix(numLTF);
|
||||||
|
R = Pheltf(1,1:numLTF); % R matrix changes pilot polarity per symbol
|
||||||
|
% Estimate the channel at pilot subcarriers accounting for polarity
|
||||||
|
chanEstSSPilots = bsxfun(@rdivide,demodHELTFRU(ofdmInfo.PilotIndices,:,:),bsxfun(@times,HELTFRU(ofdmInfo.PilotIndices),R));
|
||||||
|
varargout{1} = chanEstSSPilots*eta; % Scale for HE_EXT_SU
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
function chanEstRUInterp = chanEstInterp(chanEstRU,cbw,N_HE_LTF_Mode,ruSize,ruIndex,varargin)
|
||||||
|
% Interpolate over pilot locations and compressed subcarriers
|
||||||
|
|
||||||
|
Nfft = 256*cbw/20;
|
||||||
|
|
||||||
|
% Get the subcarrier indices within the FFT for the channel estimate
|
||||||
|
% input
|
||||||
|
kAct = wlan.internal.heRUSubcarrierIndices(cbw,ruSize,ruIndex)+Nfft/2+1;
|
||||||
|
% If the channelEstRU is not the entire RU, then we need to make sure
|
||||||
|
% we know the subcarrier indices, so use the ruInd input. For example
|
||||||
|
% this allows us to pass in only the data subcarriers.
|
||||||
|
if nargin>5
|
||||||
|
ruInd = varargin{1};
|
||||||
|
kChanEstInputs = kAct(ruInd);
|
||||||
|
else
|
||||||
|
% Assume chanEstRU is the whole RU
|
||||||
|
kChanEstInputs = kAct;
|
||||||
|
end
|
||||||
|
|
||||||
|
% Get the indices within the FFT which contain actual estimates
|
||||||
|
% (excluding the guard bands). This is how the pattern is structured
|
||||||
|
kAll = 1:N_HE_LTF_Mode:Nfft;
|
||||||
|
|
||||||
|
% Find the subcarrier indices within the FFT which contain actual data
|
||||||
|
% within the channel estimate input (kToInterp) and the indices of
|
||||||
|
% these within the chanEstDataRU input array (toInterpInd)
|
||||||
|
[kToInterp,toInterpInd] = intersect(kChanEstInputs,kAll);
|
||||||
|
|
||||||
|
% Interpolate and extrapolate over all RU subcarrier indices to
|
||||||
|
% interpolate over compressed region and pilots
|
||||||
|
magPart = interp1(kToInterp.',abs(chanEstRU(toInterpInd,:,:)),kAct,'linear','extrap');
|
||||||
|
phasePart = interp1(kToInterp.',unwrap(angle(chanEstRU(toInterpInd,:,:))),kAct,'linear','extrap');
|
||||||
|
[realPart,imagPart] = pol2cart(phasePart,magPart);
|
||||||
|
chanEstRUInterp = complex(realPart,imagPart);
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
function chanEstRUData = removeOrthogonalSequence(chanEstRUData,numSTSRU,k,N_HE_LTF_Mode)
|
||||||
|
% Remove the orthogonal sequence across subcarriers
|
||||||
|
M = 0; % Assume space-time streams of all users in estimate
|
||||||
|
m = 1:numSTSRU;
|
||||||
|
Pheltf = wlan.internal.mappingMatrix(8);
|
||||||
|
seq = Pheltf(M+m,mod(ceil(k/N_HE_LTF_Mode)-1,8)+1).'; % Nsts-by-Nst
|
||||||
|
chanEstRUData = chanEstRUData./seq;
|
||||||
|
end
|
115
heMUCalculateSteeringMatrix.m
Normal file
115
heMUCalculateSteeringMatrix.m
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
function steeringMatBF = heMUCalculateSteeringMatrix(steeringMatFB,cfg,cfgNDP,ruIdx)
|
||||||
|
%heMUCalculateSteeringMatrix Calculate beamforming steering matrix
|
||||||
|
%
|
||||||
|
% Note: This is an internal undocumented function and its API and/or
|
||||||
|
% functionality may change in subsequent releases.
|
||||||
|
%
|
||||||
|
% STEERINGMATBF = heMUCalculateSteeringMatrix(STEERINGMATFB,CFG,CFGNDP,RUIDX)
|
||||||
|
% returns the steering matrix recommended to beamform an RU in a transmit
|
||||||
|
% beamforming, or MU-MIMO configuration. ZF precoding is used.
|
||||||
|
%
|
||||||
|
% STEERINGMATFB is a cell array containing the steering matrices fed-back
|
||||||
|
% by each user in the RU to beamform.
|
||||||
|
%
|
||||||
|
% CFG is the configuration of the HE-MU transmission and is a format
|
||||||
|
% configuration object of type
|
||||||
|
% <a href="matlab:help('wlanHEMUConfig')">wlanHEMUConfig</a>.
|
||||||
|
%
|
||||||
|
% CFGNDP is the configuration of the HE-NDP used to gather feedback and
|
||||||
|
% is a format configuration object of type
|
||||||
|
% <a href="matlab:help('wlanHESUConfig')">wlanHESUConfig</a>.
|
||||||
|
%
|
||||||
|
% RUIDX is the RU index.
|
||||||
|
|
||||||
|
% Copyright 2018 The MathWorks, Inc.
|
||||||
|
|
||||||
|
allocInfo = ruInfo(cfg);
|
||||||
|
% Indices of active subcarriers within the RU
|
||||||
|
ruOFDMInfo = wlanHEOFDMInfo('HE-Data',cfg,ruIdx);
|
||||||
|
ruInd = ruOFDMInfo.ActiveFrequencyIndices;
|
||||||
|
|
||||||
|
% Indices of active subcarriers in the NDP
|
||||||
|
ndpOFDMInfo = wlanHEOFDMInfo('HE-Data',cfgNDP);
|
||||||
|
trainingInd = ndpOFDMInfo.ActiveFrequencyIndices;
|
||||||
|
|
||||||
|
% Get the indices which overlap - use to extract from NDP
|
||||||
|
[~,scUseInd] = intersect(trainingInd,ruInd);
|
||||||
|
|
||||||
|
% Extract the RU of interest from the full bandwidth grid
|
||||||
|
numUsers = allocInfo.NumUsersPerRU(ruIdx);
|
||||||
|
steeringMatUse = cell(numUsers,1);
|
||||||
|
|
||||||
|
for i = 1:numUsers
|
||||||
|
% Only take the RU subcarriers and space-time streams of
|
||||||
|
% interest for the current RU and user
|
||||||
|
userIdx = cfg.RU{ruIdx}.UserNumbers(i);
|
||||||
|
numSTS = cfg.User{userIdx}.NumSpaceTimeStreams;
|
||||||
|
numRx = size(steeringMatFB{userIdx},2);
|
||||||
|
if numSTS>numRx
|
||||||
|
error('The number of space-time streams (%d) exceeds the number of receive antennas (%d) for user %d',numSTS,numRx,userIdx);
|
||||||
|
end
|
||||||
|
steeringMatUse{i} = steeringMatFB{userIdx}(scUseInd,1:numSTS,:);
|
||||||
|
end
|
||||||
|
|
||||||
|
% Extract steering matrix for each RU
|
||||||
|
if numUsers>1
|
||||||
|
steeringMatBF = muSteeringMatrixFromFeedback(steeringMatUse);
|
||||||
|
else
|
||||||
|
steeringMatBF = steeringMatUse{1};
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
function steeringMatrix = muSteeringMatrixFromFeedback(mappingMatrix,varargin)
|
||||||
|
% Q = muSteeringMatrixFromFeedback(QU) calculates the spatial mapping
|
||||||
|
% matrix for a MU transmission using the ZF algorithm.
|
||||||
|
%
|
||||||
|
% Q is an Nst-by-Nsts-by-Nt mapping matrix. Nst is the number of
|
||||||
|
% subcarriers, Nsts is the total number of space-time streams, and Nt is
|
||||||
|
% the number of transmit antennas.
|
||||||
|
%
|
||||||
|
% QU is a cell array containing the individual mapping matrix for each
|
||||||
|
% user. Each element of QU is sized Nst-by-Nstsu-by-Nt, where Nstsu is
|
||||||
|
% the number of space-time streams for the individual user.
|
||||||
|
%
|
||||||
|
% Q = muSteeringMatrixFromFeedback(QU,SNR) calculates the spatial mapping
|
||||||
|
% matrix for a MU transmission using the MMSE algorithm given the SNR.
|
||||||
|
if nargin>1
|
||||||
|
precodingType = 'MMSE';
|
||||||
|
snr = varargin{1};
|
||||||
|
else
|
||||||
|
precodingType = 'ZF';
|
||||||
|
end
|
||||||
|
|
||||||
|
numUsers = numel(mappingMatrix);
|
||||||
|
|
||||||
|
% Get the number of STS per user
|
||||||
|
numSTS = zeros(numUsers,1);
|
||||||
|
for uIdx = 1:numUsers
|
||||||
|
numSTS(uIdx) = size(mappingMatrix{uIdx},2);
|
||||||
|
end
|
||||||
|
numSTSTotal = sum(numSTS);
|
||||||
|
|
||||||
|
% Pack the per user CSI into a matrix
|
||||||
|
[numST,~,numTx] = size(mappingMatrix{1}); % Number of subcarriers
|
||||||
|
steeringMatrix = zeros(numST,numTx,numSTSTotal); % Nst-by-Nt-by-Nsts
|
||||||
|
|
||||||
|
for uIdx = 1:numUsers
|
||||||
|
stsIdx = sum(numSTS(1:uIdx-1))+(1:numSTS(uIdx));
|
||||||
|
steeringMatrix(:,:,stsIdx) = permute(mappingMatrix{uIdx},[1 3 2]); % Nst-by-Nt-by-Nsts
|
||||||
|
end
|
||||||
|
|
||||||
|
% Zero-forcing or MMSE precoding solution
|
||||||
|
if strcmp(precodingType, 'ZF')
|
||||||
|
delta = 0; % Zero-forcing
|
||||||
|
else
|
||||||
|
delta = (numTx/(10^(snr/10))) * eye(numTx); % MMSE
|
||||||
|
end
|
||||||
|
for i = 1:numST
|
||||||
|
% Channel inversion precoding
|
||||||
|
h = squeeze(steeringMatrix(i,:,:));
|
||||||
|
steeringMatrix(i,:,:) = h/(h'*h + delta);
|
||||||
|
end
|
||||||
|
|
||||||
|
steeringMatrix = permute(steeringMatrix,[1 3 2]);
|
||||||
|
end
|
373
heMURx.m
Normal file
373
heMURx.m
Normal file
@ -0,0 +1,373 @@
|
|||||||
|
function [rxPSDU,bitErrorRate,eqSymPlot,evm] = heMURx(rx,cfg,userIdx,frameIdx,rxPSDU,cfgUI,SEED,bitErrorRate,eqSymPlot)
|
||||||
|
% [rxPSDU,eqSymUser,csiData/csi,pktFormat,evm,cfoCorrection]=heMURx(rx,cfgMUMIMO,userIdx,cfgPara);
|
||||||
|
% numBitError = 0;
|
||||||
|
% wlan ug
|
||||||
|
%% Setup Waveform Recovery Parameters
|
||||||
|
% Perform synchronization with 11ac components
|
||||||
|
chanBW = cfg.ChannelBandwidth;
|
||||||
|
fs = wlanSampleRate(cfg);
|
||||||
|
% Specify pilot tracking method for recovering the data field. This can be:
|
||||||
|
% 'Joint' - use joint common phase error and sample rate offset tracking
|
||||||
|
% 'CPE' - use only common phase error tracking
|
||||||
|
% When recovering 26-tone RUs only CPE tracking is used as the joint
|
||||||
|
% tracking algorithm is susceptible to noise.
|
||||||
|
pilotTracking = 'Joint';
|
||||||
|
% Create an HE recovery configuration object and set the channel bandwidth
|
||||||
|
cfgRx = wlanHERecoveryConfig;
|
||||||
|
cfgRx.ChannelBandwidth = chanBW;
|
||||||
|
|
||||||
|
% Get the field indices for extract fields from the PPDU
|
||||||
|
% ind = wlanFieldIndices(cfg);
|
||||||
|
ind = wlanFieldIndices(cfgRx);
|
||||||
|
|
||||||
|
% % Setup plots for the example
|
||||||
|
% [spectrumAnalyzer,timeScope,ConstellationDiagram,EVMPerSubcarrier,EVMPerSymbol] = heSigRecSetupPlots(fs);
|
||||||
|
|
||||||
|
% Minimum packet length is 10 OFDM symbols
|
||||||
|
% lstfLength = double(ind.LSTF(2));
|
||||||
|
% minPktLen = lstfLength*5; % Number of samples in L-STF
|
||||||
|
|
||||||
|
rxWaveLen = size(rx,1);
|
||||||
|
|
||||||
|
%% Front-End Processing
|
||||||
|
searchOffset = 0; % Offset from start of waveform in samples
|
||||||
|
% Packet detection
|
||||||
|
coarsePktOffset = wlanPacketDetect(rx,chanBW,searchOffset,0.8);
|
||||||
|
LSTF = wlanLSTF(wlanNonHTConfig);
|
||||||
|
% if isempty(coarsePktOffset)||(coarsePktOffset + ind.LSIG(2) > rxWaveLen) % If empty no L-STF detected; packet error
|
||||||
|
% numBitError = numBitError+numBits;%%???????????????
|
||||||
|
% userIdx = userIdx+1;
|
||||||
|
% end
|
||||||
|
% Coarse frequency offset estimation and correction using L-STF
|
||||||
|
if isempty(coarsePktOffset)
|
||||||
|
coarsePktOffset = 0;
|
||||||
|
end
|
||||||
|
rxLSTF = rx(coarsePktOffset+(ind.LSTF(1):ind.LSTF(2)), :);
|
||||||
|
tmp_xcorr = abs(xcorr(LSTF,rxLSTF));
|
||||||
|
coarseFreqOffset = wlanCoarseCFOEstimate(rxLSTF,chanBW);
|
||||||
|
rx = helperFrequencyOffset(rx,fs,-coarseFreqOffset);
|
||||||
|
% Extract the non-HT fields and determine fine packet offset
|
||||||
|
nonhtfields = rx(coarsePktOffset+(ind.LSTF(1):ind.LSIG(2)),:);
|
||||||
|
finePktOffset = wlanSymbolTimingEstimate(nonhtfields,chanBW);
|
||||||
|
|
||||||
|
% Determine final packet offset
|
||||||
|
pktOffset = coarsePktOffset+finePktOffset;
|
||||||
|
|
||||||
|
% if pktOffset>50%%????????????????????????????///
|
||||||
|
% % numPacketErrors(userIdx) = numPacketErrors(userIdx)+1;
|
||||||
|
% numBitError = numBitError+numBits;
|
||||||
|
% userIdx = userIdx+1;
|
||||||
|
% % continue; % Go to next loop iteration
|
||||||
|
% end
|
||||||
|
|
||||||
|
% Extract L-LTF and perform fine frequency offset correction
|
||||||
|
rxLLTF = rx(pktOffset+(ind.LLTF(1):ind.LLTF(2)),:);
|
||||||
|
fineFreqOff = wlanFineCFOEstimate(rxLLTF,chanBW);
|
||||||
|
rx = helperFrequencyOffset(rx,fs,-fineFreqOff);
|
||||||
|
|
||||||
|
% Timing synchronization complete: packet detected
|
||||||
|
fprintf('Packet detected at index %d\n',pktOffset + 1);
|
||||||
|
|
||||||
|
% Display estimated carrier frequency offset
|
||||||
|
cfoCorrection = coarseFreqOffset + fineFreqOff; % Total CFO
|
||||||
|
fprintf('Estimated CFO: %5.1f Hz\n\n',cfoCorrection);
|
||||||
|
|
||||||
|
|
||||||
|
if max(tmp_xcorr)>50
|
||||||
|
|
||||||
|
% Scale the waveform based on L-STF power (AGC)
|
||||||
|
gain = 1./(sqrt(mean(rxLSTF.*conj(rxLSTF))));
|
||||||
|
rx = rx.*gain;
|
||||||
|
|
||||||
|
%% Packet Format Detection
|
||||||
|
|
||||||
|
rxLLTF = rx(pktOffset+(ind.LLTF(1):ind.LLTF(2)),:);
|
||||||
|
lltfDemod = wlanLLTFDemodulate(rxLLTF,chanBW);
|
||||||
|
lltfChanEst = wlanLLTFChannelEstimate(lltfDemod,chanBW);
|
||||||
|
noiseVar = helperNoiseEstimate(lltfDemod);
|
||||||
|
|
||||||
|
rxSIGA = rx(pktOffset+(ind.LSIG(1):ind.HESIGA(2)),:);
|
||||||
|
pktFormat = wlanFormatDetect(rxSIGA,lltfChanEst,noiseVar,chanBW);
|
||||||
|
fprintf(' %s packet detected\n\n',pktFormat);
|
||||||
|
|
||||||
|
% Set the packet format in the recovery object and update the field indices
|
||||||
|
cfgRx.PacketFormat = pktFormat;
|
||||||
|
ind = wlanFieldIndices(cfgRx);
|
||||||
|
|
||||||
|
%% L-LTF Channel Estimate
|
||||||
|
lltfDemod = wlanHEDemodulate(rxLLTF,'L-LTF',chanBW);
|
||||||
|
lltfChanEst = wlanLLTFChannelEstimate(lltfDemod,chanBW);
|
||||||
|
|
||||||
|
%% L-SIG and RL-SIG Decoding
|
||||||
|
% Extract L-SIG and RL-SIG fields
|
||||||
|
rxLSIG = rx(pktOffset+(ind.LSIG(1):ind.RLSIG(2)),:);
|
||||||
|
|
||||||
|
% OFDM demodulate
|
||||||
|
helsigDemod = wlanHEDemodulate(rxLSIG,'L-SIG',chanBW);
|
||||||
|
|
||||||
|
% Estimate CPE and phase correct symbols
|
||||||
|
helsigDemod = preHECommonPhaseErrorTracking(helsigDemod,lltfChanEst,'L-SIG',chanBW);
|
||||||
|
|
||||||
|
% Estimate channel on extra 4 subcarriers per subchannel and create full
|
||||||
|
% channel estimate
|
||||||
|
preheInfo = wlanHEOFDMInfo('L-SIG',chanBW);
|
||||||
|
preHEChanEst = preHEChannelEstimate(helsigDemod,lltfChanEst,preheInfo.NumSubchannels);
|
||||||
|
|
||||||
|
% Average L-SIG and RL-SIG before equalization
|
||||||
|
helsigDemod = mean(helsigDemod,2);
|
||||||
|
|
||||||
|
% Equalize data carrying subcarriers, merging 20 MHz subchannels
|
||||||
|
[eqLSIGSym,csi] = preHESymbolEqualize(helsigDemod(preheInfo.DataIndices,:,:), ...
|
||||||
|
preHEChanEst(preheInfo.DataIndices,:,:),noiseVar,preheInfo.NumSubchannels);
|
||||||
|
|
||||||
|
% Decode L-SIG field
|
||||||
|
[~,failCheck,lsigInfo] = wlanLSIGBitRecover(eqLSIGSym,noiseVar,csi);
|
||||||
|
|
||||||
|
if failCheck
|
||||||
|
disp(' ** L-SIG check fail **');
|
||||||
|
else
|
||||||
|
disp(' L-SIG check pass');
|
||||||
|
end
|
||||||
|
% Get the length information from the recovered L-SIG bits and update the
|
||||||
|
% L-SIG length property of the recovery configuration object
|
||||||
|
lsigLength = lsigInfo.Length;
|
||||||
|
cfgRx.LSIGLength = lsigLength;
|
||||||
|
|
||||||
|
% Measure EVM of L-SIG symbols
|
||||||
|
EVM = comm.EVM;
|
||||||
|
EVM.ReferenceSignalSource = 'Estimated from reference constellation';
|
||||||
|
EVM.Normalization = 'Average constellation power';
|
||||||
|
EVM.ReferenceConstellation = wlanReferenceSymbols('BPSK');
|
||||||
|
rmsEVM = EVM(eqLSIGSym);
|
||||||
|
evm = 20*log10(rmsEVM/100);
|
||||||
|
fprintf(' L-SIG EVM: %2.2fdB\n\n',20*log10(rmsEVM/100));
|
||||||
|
|
||||||
|
% Calculate the receive time and corresponding number of samples in the
|
||||||
|
% packet
|
||||||
|
RXTime = ceil((lsigLength + 3)/3) * 4 + 20; % In microseconds
|
||||||
|
numRxSamples = round(RXTime * 1e-6 * fs); % Number of samples in time
|
||||||
|
|
||||||
|
%% HE-SIG-A Decoding
|
||||||
|
rxSIGA = rx(pktOffset+(ind.HESIGA(1):ind.HESIGA(2)),:);
|
||||||
|
sigaDemod = wlanHEDemodulate(rxSIGA,'HE-SIG-A',chanBW);
|
||||||
|
hesigaDemod = preHECommonPhaseErrorTracking(sigaDemod,preHEChanEst,'HE-SIG-A',chanBW);
|
||||||
|
|
||||||
|
% Equalize data carrying subcarriers, merging 20 MHz subchannels
|
||||||
|
preheInfo = wlanHEOFDMInfo('HE-SIG-A',chanBW);
|
||||||
|
[eqSIGASym,csi] = preHESymbolEqualize(hesigaDemod(preheInfo.DataIndices,:,:), ...
|
||||||
|
preHEChanEst(preheInfo.DataIndices,:,:), ...
|
||||||
|
noiseVar,preheInfo.NumSubchannels);
|
||||||
|
% Recover HE-SIG-A bits
|
||||||
|
[sigaBits,failCRC] = wlanHESIGABitRecover(eqSIGASym,noiseVar,csi);
|
||||||
|
|
||||||
|
% Perform the CRC on HE-SIG-A bits
|
||||||
|
if failCRC
|
||||||
|
disp(' ** HE-SIG-A CRC fail **');
|
||||||
|
else
|
||||||
|
disp(' HE-SIG-A CRC pass');
|
||||||
|
end
|
||||||
|
|
||||||
|
% Measure EVM of HE-SIG-A symbols
|
||||||
|
% release(EVM);
|
||||||
|
% if strcmp(pktFormat,'HE-EXT-SU')
|
||||||
|
% % The second symbol of an HE-SIG-A field for an HE-EXT-SU packet is
|
||||||
|
% % QBPSK.
|
||||||
|
% EVM.ReferenceConstellation = wlanReferenceSymbols('BPSK',[0 pi/2 0 0]);
|
||||||
|
% % Account for scaling of L-LTF for an HE-EXT-SU packet
|
||||||
|
% rmsEVM = EVM(eqSIGASym*sqrt(2));
|
||||||
|
% else
|
||||||
|
% EVM.ReferenceConstellation = wlanReferenceSymbols('BPSK');
|
||||||
|
% rmsEVM = EVM(eqSIGASym);
|
||||||
|
% end
|
||||||
|
% fprintf(' HE-SIG-A EVM: %2.2fdB\n\n',20*log10(mean(rmsEVM)/100));
|
||||||
|
|
||||||
|
%% Interpret Recovered HE-SIG-A bits
|
||||||
|
cfgRx = interpretHESIGABits(cfgRx,sigaBits);
|
||||||
|
ind = wlanFieldIndices(cfgRx); % Update field indices
|
||||||
|
% disp(cfgRx)
|
||||||
|
|
||||||
|
|
||||||
|
%% HE-SIG-B Decoding
|
||||||
|
if strcmp(pktFormat,'HE-MU')
|
||||||
|
if ~cfgRx.SIGBCompression
|
||||||
|
s = getSIGBLength(cfgRx);
|
||||||
|
% Get common field symbols. The start of HE-SIG-B field is known
|
||||||
|
rxSym = rx(pktOffset+(ind.HESIGA(2)+(1:s.NumSIGBCommonFieldSamples)),:);
|
||||||
|
% Decode HE-SIG-B common field
|
||||||
|
[status,cfgRx] = heSIGBCommonFieldDecode(rxSym,preHEChanEst,noiseVar,cfgRx);
|
||||||
|
|
||||||
|
% CRC on HE-SIG-B content channels
|
||||||
|
if strcmp(status,'Success')
|
||||||
|
fprintf(' HE-SIG-B (common field) CRC pass\n');
|
||||||
|
elseif strcmp(status,'ContentChannel1CRCFail')
|
||||||
|
fprintf(' ** HE-SIG-B CRC fail for content channel-1\n **');
|
||||||
|
elseif strcmp(status,'ContentChannel2CRCFail')
|
||||||
|
fprintf(' ** HE-SIG-B CRC fail for content channel-2\n **');
|
||||||
|
elseif any(strcmp(status,{'UnknownNumUsersContentChannel1','UnknownNumUsersContentChannel2'}))
|
||||||
|
error(' ** Unknown packet length, discard packet\n **');
|
||||||
|
else
|
||||||
|
% Discard the packet if all HE-SIG-B content channels fail
|
||||||
|
error(' ** HE-SIG-B CRC fail **');
|
||||||
|
end
|
||||||
|
% Update field indices as the number of HE-SIG-B symbols are
|
||||||
|
% updated
|
||||||
|
ind = wlanFieldIndices(cfgRx);
|
||||||
|
end
|
||||||
|
|
||||||
|
% Get complete HE-SIG-B field samples
|
||||||
|
rxSIGB = rx(pktOffset+(ind.HESIGB(1):ind.HESIGB(2)),:);
|
||||||
|
fprintf(' Decoding HE-SIG-B user field... \n');
|
||||||
|
% Decode HE-SIG-B user field
|
||||||
|
[failCRC,cfgUsers] = heSIGBUserFieldDecode(rxSIGB,preHEChanEst,noiseVar,cfgRx);
|
||||||
|
%*********************************03.22修改*********************************
|
||||||
|
for ii = 1:numel(cfgUsers)
|
||||||
|
if cfgUsers{ii}.STAID == userIdx
|
||||||
|
user = cfgUsers{ii};
|
||||||
|
break;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
% user = cfgUsers{1};
|
||||||
|
%*********************************03.22修改*********************************
|
||||||
|
% CRC on HE-SIG-B users
|
||||||
|
if ~all(failCRC)
|
||||||
|
fprintf(' HE-SIG-B (user field) CRC pass\n\n');
|
||||||
|
numUsers = numel(cfgUsers);
|
||||||
|
elseif all(failCRC)
|
||||||
|
% Discard the packet if all users fail the CRC
|
||||||
|
error(' ** HE-SIG-B CRC fail for all users **');
|
||||||
|
else
|
||||||
|
fprintf(' ** HE-SIG-B CRC fail for at least one user\n **');
|
||||||
|
% Only process users with valid CRC
|
||||||
|
numUsers = numel(cfgUsers);
|
||||||
|
end
|
||||||
|
|
||||||
|
else % HE-SU, HE-EXT-SU
|
||||||
|
cfgUsers = {cfgRx};
|
||||||
|
numUsers = 1;
|
||||||
|
end
|
||||||
|
|
||||||
|
%% HE-Data Decoding
|
||||||
|
cfgDataRec = trackingRecoveryConfig;
|
||||||
|
cfgDataRec.PilotTracking = pilotTracking;
|
||||||
|
% Get recovery configuration object for each user
|
||||||
|
user = cfgUsers{userIdx};
|
||||||
|
if strcmp(pktFormat,'HE-MU')
|
||||||
|
fprintf(' Decoding User:%d, STAID:%d, RUSize:%d\n',userIdx,user.STAID,user.RUSize);
|
||||||
|
else
|
||||||
|
fprintf(' Decoding RUSize:%d\n',user.RUSize);
|
||||||
|
end
|
||||||
|
|
||||||
|
heInfo = wlanHEOFDMInfo('HE-Data',chanBW,user.GuardInterval,[user.RUSize user.RUIndex]);
|
||||||
|
|
||||||
|
% HE-LTF demodulation and channel estimation
|
||||||
|
rxHELTF = rx(pktOffset+(ind.HELTF(1):ind.HELTF(2)),:);
|
||||||
|
heltfDemod = wlanHEDemodulate(rxHELTF,'HE-LTF',chanBW,user.GuardInterval, ...
|
||||||
|
user.HELTFType,[user.RUSize user.RUIndex]);
|
||||||
|
[chanEst,pilotEst] = heLTFChannelEstimate(heltfDemod,user);
|
||||||
|
|
||||||
|
% Number of expected data OFDM symbols
|
||||||
|
symLen = heInfo.FFTLength+heInfo.CPLength;
|
||||||
|
numOFDMSym = (ind.HEData(2)-ind.HEData(1)+1)/symLen;
|
||||||
|
numOFDMSym = double(numOFDMSym);
|
||||||
|
|
||||||
|
% HE-Data demodulation with pilot phase and timing tracking
|
||||||
|
% Account for extra samples when extracting data field from the packet
|
||||||
|
% for sample rate offset tracking. Extra samples may be required if the
|
||||||
|
% receiver clock is significantly faster than the transmitter.
|
||||||
|
maxSRO = 120; % Parts per million
|
||||||
|
Ne = ceil(numRxSamples*maxSRO*1e-6); % Number of extra samples
|
||||||
|
Ne = min(Ne,rxWaveLen-numRxSamples); % Limited to length of waveform
|
||||||
|
numRxSamplesProcess = numRxSamples+Ne;
|
||||||
|
rxData = rx(pktOffset+(ind.HEData(1):numRxSamplesProcess),:);
|
||||||
|
if user.RUSize==26
|
||||||
|
% Force CPE only tracking for 26-tone RU as algorithm susceptible
|
||||||
|
% to noise
|
||||||
|
cfgDataRec.PilotTracking = 'CPE';
|
||||||
|
else
|
||||||
|
cfgDataRec.PilotTracking = pilotTracking;
|
||||||
|
end
|
||||||
|
[demodSym,cpe,peg] = heTrackingOFDMDemodulate(rxData,chanEst,numOFDMSym,user,cfgDataRec);
|
||||||
|
|
||||||
|
% Estimate noise power in HE fields
|
||||||
|
demodPilotSym = demodSym(heInfo.PilotIndices,:,:);
|
||||||
|
nVarEst = heNoiseEstimate(demodPilotSym,pilotEst,user);
|
||||||
|
|
||||||
|
% Equalize
|
||||||
|
[eqSym,csi] = heEqualizeCombine(demodSym,chanEst,nVarEst,user);
|
||||||
|
|
||||||
|
% Discard pilot subcarriers
|
||||||
|
eqSymUser = eqSym(heInfo.DataIndices,:,:);
|
||||||
|
csiData = csi(heInfo.DataIndices,:);
|
||||||
|
eqSymPlot = eqSymUser(1:end);
|
||||||
|
|
||||||
|
% scatterplot
|
||||||
|
% eqSymplot = eqSymUser(1:end);
|
||||||
|
% scatterplot(eqSymplot);
|
||||||
|
|
||||||
|
% Demap and decode bits
|
||||||
|
rxPSDUbits = wlanHEDataBitRecover(eqSymUser,nVarEst,csiData,user,'LDPCDecodingMethod','layered-bp');
|
||||||
|
% rxPSDU(:,frameIdx) = RX_CRC32(double(rxPSDUbits));
|
||||||
|
rxPSDU(:,frameIdx) = rxPSDUbits;
|
||||||
|
% Compare bit error
|
||||||
|
% bitError = sum(txPSDU{userIdx}~=rxPSDU);
|
||||||
|
% numBitError = numBitError+bitError;
|
||||||
|
|
||||||
|
% Measure EVM of HE-Data symbols
|
||||||
|
release(EVM);
|
||||||
|
EVM.ReferenceConstellation = wlanReferenceSymbols(user);
|
||||||
|
rmsEVM = EVM(eqSymUser(:));
|
||||||
|
fprintf(' HE-Data EVM:%2.2fdB\n\n',20*log10(rmsEVM/100));
|
||||||
|
rx = rx(pktOffset+ind.HEData(2)+100:end,:);
|
||||||
|
% && mean(abs(rx)) > mean_power/2
|
||||||
|
% else
|
||||||
|
|
||||||
|
% if length(rx) > ind.HEData(2)
|
||||||
|
frameIdx = frameIdx+1;
|
||||||
|
[rxPSDU,bitErrorRate,eqSymPlot] = heMURx(rx,cfg,userIdx,frameIdx,rxPSDU,cfgUI,SEED,bitErrorRate,eqSymPlot);
|
||||||
|
else
|
||||||
|
[~,numPkt] = size(rxPSDU);
|
||||||
|
psduLength = length(rxPSDU(:,1))/8;
|
||||||
|
|
||||||
|
switch cfgUI.DataType
|
||||||
|
case 'test'
|
||||||
|
txPSDU = DataGenerate(cfgUI,numPkt,SEED,psduLength,0);
|
||||||
|
txPSDUuser = txPSDU{userIdx};% BER计算方式 用收发约定的种子数产生,解5个包确定ACK个数
|
||||||
|
bitError = sum(txPSDUuser(1:end,:)~=rxPSDU(1:length(txPSDUuser(1:end,:)),:));
|
||||||
|
bitErrorRate = bitError/length(rxPSDU);
|
||||||
|
ACK = (bitErrorRate == rxPSDU(end));
|
||||||
|
case 'text'
|
||||||
|
case 'photo'
|
||||||
|
[~,numPkt] = size(rxPSDU);
|
||||||
|
bitstream = reshape(rxPSDU,1,[]); % 恢复比特变比特流
|
||||||
|
imgLen = bin2dec(num2str(bitstream(1:16)));
|
||||||
|
% bitstream = bitstream(1:len*width*8); % 取图像像素大小
|
||||||
|
bit_array = reshape(bitstream,8,[])';
|
||||||
|
byte_array = num2str(bit_array);
|
||||||
|
img = bin2dec(byte_array); % 二进制转十进制
|
||||||
|
if imgLen+3 > length(img)
|
||||||
|
imgLen = length(img)-3;
|
||||||
|
end
|
||||||
|
rxPSDU = int16(img(1:imgLen+3)); % double转int16
|
||||||
|
rxCRC = 0;
|
||||||
|
for i = 1:imgLen+2
|
||||||
|
rxCRC = mod(rxCRC+rxPSDU(i),256);
|
||||||
|
end
|
||||||
|
if rxCRC == rxPSDU(end)
|
||||||
|
disp('Pass RX Sum Check!');
|
||||||
|
bitErrorRate = zeros(1,numPkt);
|
||||||
|
else
|
||||||
|
disp('Fail RX Sum Check!');
|
||||||
|
bitErrorRate = ones(1,numPkt);
|
||||||
|
end
|
||||||
|
% img = mat2gray(rxPSDU); % 恢复出的数据按图像大小排列
|
||||||
|
% imshow(img); % 展示图像
|
||||||
|
% pause(1);
|
||||||
|
% close;
|
||||||
|
ACK = (rxCRC == rxPSDU(end));
|
||||||
|
end
|
||||||
|
save(['TXPackets\ACKfeedback_for_User' num2str(userIdx) '.mat'],'ACK');
|
||||||
|
% scatterplot(eqSymPlot(1:end));
|
||||||
|
% pause(1);
|
||||||
|
% close;
|
||||||
|
end
|
||||||
|
end
|
106
heNoiseEstimate.m
Normal file
106
heNoiseEstimate.m
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
function [nest,sigest] = heNoiseEstimate(x,chanEstSSPilots,cfg,varargin)
|
||||||
|
%heNoiseEstimate Estimate noise power using HE data field pilots
|
||||||
|
%
|
||||||
|
% NEST = heNoiseEstimate(x,CHANESTSSPILOTS,CFGHE) estimates the mean
|
||||||
|
% noise power in watts using the demodulated pilot symbols in the HE data
|
||||||
|
% field and single-stream channel estimates at pilot subcarriers. The
|
||||||
|
% noise estimate is averaged over the number of symbols and receive
|
||||||
|
% antennas.
|
||||||
|
%
|
||||||
|
% X is a complex Nsp-by-Nsym-by-Nr array containing demodulated pilot
|
||||||
|
% subcarrier in HE data field. Nsym is the number of demodulated HE-Data
|
||||||
|
% symbols.
|
||||||
|
%
|
||||||
|
% CHANESTSSPILOTS is a complex Nsp-by-Nltf-by-Nr array containing the
|
||||||
|
% channel gains at pilot subcarrier locations for each symbol, assuming
|
||||||
|
% one space-time stream at the transmitter. Nltf is the number of HE-LTF
|
||||||
|
% symbols.
|
||||||
|
%
|
||||||
|
% CFGHE is a format configuration object of type <a href="matlab:help('wlanHESUConfig')">wlanHESUConfig</a>,
|
||||||
|
% <a href="matlab:help('wlanHETBConfig')">wlanHETBConfig</a> or <a href="matlab:help('wlanHERecoveryConfig')">wlanHERecoveryConfig</a>.
|
||||||
|
%
|
||||||
|
% NEST = heNoiseEstimate(X,CHANESTSSPILOTS,CFGMU,RUIDX) performs noise
|
||||||
|
% power estimation for the multi user HE format input X.
|
||||||
|
%
|
||||||
|
% CFGMU is the format configuration object of type <a href="matlab:help('wlanHEMUConfig')">wlanHEMUConfig</a> or
|
||||||
|
% <a href="matlab:help('heTBSystemConfig')">heTBSystemConfig</a>.
|
||||||
|
%
|
||||||
|
% RUIDX is the RU (resource unit) index.
|
||||||
|
%
|
||||||
|
% [NEST,SIGEST] = heNoiseEstimate(...) additionally returns an estimate
|
||||||
|
% of the signal power.
|
||||||
|
|
||||||
|
% Copyright 2018-2019 The MathWorks, Inc.
|
||||||
|
|
||||||
|
%#codegen
|
||||||
|
|
||||||
|
validateattributes(cfg,{'wlanHESUConfig','wlanHEMUConfig','wlanHETBConfig','wlanHERecoveryConfig','heTBSystemConfig'},{'scalar'},mfilename,'format configuration object');
|
||||||
|
|
||||||
|
numOFDMSym = size(x,2);
|
||||||
|
n = (0:numOFDMSym-1);
|
||||||
|
|
||||||
|
ruIdx = 1;
|
||||||
|
if isa(cfg,'wlanHEMUConfig')
|
||||||
|
narginchk(4,4)
|
||||||
|
ruIdx = varargin{1};
|
||||||
|
sigbInfo = wlan.internal.heSIGBCodingInfo(cfg);
|
||||||
|
numHESIGB = sigbInfo.NumSymbols;
|
||||||
|
pktFormat = packetFormat(cfg);
|
||||||
|
allocInfo = ruInfo(cfg);
|
||||||
|
ruSize = allocInfo.RUSizes(ruIdx);
|
||||||
|
elseif isa(cfg,'heTBSystemConfig')
|
||||||
|
numHESIGB = 0;
|
||||||
|
ruIdx = varargin{1};
|
||||||
|
pktFormat = packetFormat(cfg);
|
||||||
|
allocInfo = ruInfo(cfg);
|
||||||
|
ruSize = allocInfo.RUSizes(ruIdx);
|
||||||
|
elseif isa(cfg,'wlanHERecoveryConfig')
|
||||||
|
ruSize = cfg.RUSize;
|
||||||
|
pktFormat = cfg.PacketFormat;
|
||||||
|
if strcmp(pktFormat,'HE-MU')
|
||||||
|
s = getSIGBLength(cfg);
|
||||||
|
numHESIGB = s.NumSIGBSymbols;
|
||||||
|
else
|
||||||
|
numHESIGB = 0;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
% SU, EXT SU, TB
|
||||||
|
numHESIGB = 0;
|
||||||
|
pktFormat = packetFormat(cfg);
|
||||||
|
allocInfo = ruInfo(cfg);
|
||||||
|
ruSize = allocInfo.RUSizes(ruIdx);
|
||||||
|
end
|
||||||
|
|
||||||
|
if strcmp(pktFormat,'HE-EXT-SU')
|
||||||
|
numHESIGA = 4;
|
||||||
|
else % SU or MU
|
||||||
|
numHESIGA = 2;
|
||||||
|
end
|
||||||
|
|
||||||
|
z = 2+numHESIGA+numHESIGB; % Pilot symbol offset
|
||||||
|
% Get the reference pilots for one space-time stream, pilot sequence same
|
||||||
|
% for all space-time streams
|
||||||
|
refPilots = wlan.internal.hePilots(ruSize,1,n,z); % Nsp-by-Nsym-by-1
|
||||||
|
|
||||||
|
% Average single-stream pilot estimates over symbols (2nd dimension)
|
||||||
|
avChanEstSSPilots = mean(chanEstSSPilots,2); % Nsp-by-1-by-Nrx
|
||||||
|
|
||||||
|
% Estimate channel at pilot location using least square estimates
|
||||||
|
chanEstPilotsLoc = bsxfun(@rdivide,x,refPilots); % Nsp-by-Nsym-by-Nrx
|
||||||
|
|
||||||
|
% Subtract the noisy least squares estimates of the channel at pilot symbol
|
||||||
|
% locations from the noise averaged single stream pilot symbol estimates of
|
||||||
|
% the channel
|
||||||
|
error = bsxfun(@minus,chanEstPilotsLoc,avChanEstSSPilots); % Nsp-by-Nsym-by-Nrx
|
||||||
|
|
||||||
|
% Get power of error and average over pilot symbols, subcarriers and
|
||||||
|
% receive antennas
|
||||||
|
useIdx = ~isnan(error); % NaNs may exist in 1xHELTF
|
||||||
|
nest = real(mean(error(useIdx).*conj(error(useIdx)),'all')); % For codegen
|
||||||
|
|
||||||
|
if nargout>1
|
||||||
|
% Get power of channel estimate at pilot locations
|
||||||
|
sigest = real(mean(chanEstPilotsLoc(:).*conj(chanEstPilotsLoc(:)))); % For codegen
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
50
hePlotEQConstellation.m
Normal file
50
hePlotEQConstellation.m
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
function hePlotEQConstellation(eqDataSym,cfgRx,ConstellationDiagram,varargin)
|
||||||
|
% hePlotEQConstellation Plot equalized constellation for all spatial streams
|
||||||
|
%
|
||||||
|
% hePlotEQConstellation(EQDATASYM,CFGRX,CONSTELLATIONDIAGRAM) plots
|
||||||
|
% equalized constellation for all spatial streams.
|
||||||
|
%
|
||||||
|
% EQDATASYM are the demodulated HE-Data field OFDM symbols for a user,
|
||||||
|
% specified as a Nsd-by-Nsym-by-Nss matrix of real or complex values,
|
||||||
|
% where Nsd is the number of data subcarriers in the HE-Data field and
|
||||||
|
% Nsym is the number of OFDM symbols, and Nss is the number of spatial
|
||||||
|
% streams.
|
||||||
|
%
|
||||||
|
% CFGRX is the format configuration object of type <a href="matlab:help('wlanHERecoveryConfig')">wlanHERecoveryConfig</a>.
|
||||||
|
%
|
||||||
|
% CONSTELLATIONDIAGRAM is a system object of type <a href="matlab:help('comm.ConstellationDiagram')">comm.ConstellationDiagram</a>.
|
||||||
|
%
|
||||||
|
% hePlotEQConstellation(...,USERIDX,NUMUSERS) displays user number and
|
||||||
|
% number of user information in the figure title.
|
||||||
|
|
||||||
|
% Copyright 2019 The MathWorks, Inc.
|
||||||
|
|
||||||
|
if nargin==5
|
||||||
|
userIdx = varargin{1};
|
||||||
|
numUsers = varargin{2};
|
||||||
|
elseif nargin==4
|
||||||
|
userIdx = varargin{1};
|
||||||
|
numUsers = 1;
|
||||||
|
end
|
||||||
|
|
||||||
|
[Nsd,Nsym,Nss] = size(eqDataSym);
|
||||||
|
eqDataSymPerSS = reshape(eqDataSym,Nsd*Nsym,Nss);
|
||||||
|
|
||||||
|
str = cell(Nss,1);
|
||||||
|
for iss=1:Nss
|
||||||
|
str{iss} = sprintf('Spatial stream %d',iss);
|
||||||
|
end
|
||||||
|
|
||||||
|
ConstellationDiagram.ReferenceConstellation = wlanReferenceSymbols(cfgRx);
|
||||||
|
ConstellationDiagram(eqDataSymPerSS);
|
||||||
|
show(ConstellationDiagram);
|
||||||
|
|
||||||
|
if nargin>3
|
||||||
|
ConstellationDiagram.Name = sprintf('Equalized data symbols, user #%d/%d',userIdx,numUsers);
|
||||||
|
else
|
||||||
|
ConstellationDiagram.Name = sprintf('Equalized data symbols');
|
||||||
|
end
|
||||||
|
ConstellationDiagram.ChannelNames = str;
|
||||||
|
release(ConstellationDiagram);
|
||||||
|
|
||||||
|
end
|
76
hePlotEVMPerSubcarrier.m
Normal file
76
hePlotEVMPerSubcarrier.m
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
function rmsEVM = hePlotEVMPerSubcarrier(eqDataSym,cfgRx,evmSubcarrierPlot,varargin)
|
||||||
|
% hePlotEVMPerSubcarrier Plots EVM per subcarrier for all spatial streams
|
||||||
|
%
|
||||||
|
% RMSEVM = hePlotEVMPerSubcarrier(EQDATASYM,CFGRX,EVMSUBCARRIERPLOT)
|
||||||
|
% plots EVM per subcarriers averaged over symbols for all spatial
|
||||||
|
% streams.
|
||||||
|
%
|
||||||
|
% RMSEVM is the EVM of EQDATASYM in decibels.
|
||||||
|
%
|
||||||
|
% EQDATASYM are the demodulated HE-Data field OFDM symbols for a user,
|
||||||
|
% specified as a Nsd-by-Nsym-by-Nss matrix of real or complex values,
|
||||||
|
% where Nsd is the number of data subcarriers in the HE-Data field and
|
||||||
|
% Nsym is the number of OFDM symbols, and Nss is the number of spatial
|
||||||
|
% streams.
|
||||||
|
%
|
||||||
|
% CFGRX is the format configuration object of type <a href="matlab:help('wlanHERecoveryConfig')">wlanHERecoveryConfig</a>,
|
||||||
|
% <a href="matlab:help('wlanHESUConfig')">wlanHESUConfig</a>, or <a href="matlab:help('wlanHETBConfig')">wlanHETBConfig</a>.
|
||||||
|
%
|
||||||
|
% EVMSUBCARRIERPLOT is a system object of type <a href="matlab:help('dsp.ArrayPlot')">dsp.ArrayPlot</a>.
|
||||||
|
%
|
||||||
|
% RMSEVM = hePlotEVMPerSubcarrier(...,USERIDX,NUMUSERS) displays user
|
||||||
|
% number and number of user information in the figure title.
|
||||||
|
|
||||||
|
% Copyright 2019-2020 The MathWorks, Inc.
|
||||||
|
|
||||||
|
[Nsd,~,Nss] = size(eqDataSym);
|
||||||
|
rmsEVMPerSC = zeros(Nsd,Nss);
|
||||||
|
|
||||||
|
if nargin == 5
|
||||||
|
userIdx = varargin{1};
|
||||||
|
numUsers = varargin{2};
|
||||||
|
elseif nargin == 4
|
||||||
|
userIdx = varargin{1};
|
||||||
|
numUsers = 1; % Number of users are unknown, prefix this to 1
|
||||||
|
end
|
||||||
|
|
||||||
|
EVM = comm.EVM;
|
||||||
|
EVM.ReferenceSignalSource = 'Estimated from reference constellation';
|
||||||
|
EVM.ReferenceConstellation = wlanReferenceSymbols(cfgRx);
|
||||||
|
|
||||||
|
for iss = 1:Nss
|
||||||
|
for isd = 1:Nsd
|
||||||
|
rmsEVMPerSC(isd,iss) = EVM(eqDataSym(isd,:,iss).');
|
||||||
|
release(EVM);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if isa(cfgRx,'wlanHERecoveryConfig')
|
||||||
|
ofdmInfo = wlanHEOFDMInfo('HE-Data',cfgRx.ChannelBandwidth,cfgRx.GuardInterval,[cfgRx.RUSize cfgRx.RUIndex]);
|
||||||
|
else
|
||||||
|
ofdmInfo = wlanHEOFDMInfo('HE-Data',cfgRx);
|
||||||
|
end
|
||||||
|
dataInd = ofdmInfo.ActiveFFTIndices(ofdmInfo.DataIndices);
|
||||||
|
Nfft = ofdmInfo.FFTLength;
|
||||||
|
|
||||||
|
evmFFT = nan(Nfft,Nss);
|
||||||
|
rmsEVM = 20*log10(rmsEVMPerSC/100);
|
||||||
|
evmFFT(dataInd,:) = rmsEVM;
|
||||||
|
evmSubcarrierPlot.XOffset = -Nfft/2;
|
||||||
|
|
||||||
|
str = cell(Nss,1);
|
||||||
|
for iss=1:Nss
|
||||||
|
str{iss} = sprintf('Spatial stream %d',iss);
|
||||||
|
end
|
||||||
|
|
||||||
|
evmSubcarrierPlot.ChannelNames = str;
|
||||||
|
if nargin>3
|
||||||
|
evmSubcarrierPlot.Name = sprintf('EVM per subcarrier, user#%d/%d',userIdx,numUsers);
|
||||||
|
else
|
||||||
|
evmSubcarrierPlot.Name = sprintf('EVM per subcarrier');
|
||||||
|
end
|
||||||
|
evmSubcarrierPlot(evmFFT)
|
||||||
|
evmSubcarrierPlot.show
|
||||||
|
release(evmSubcarrierPlot);
|
||||||
|
|
||||||
|
end
|
57
hePlotEVMPerSymbol.m
Normal file
57
hePlotEVMPerSymbol.m
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
function rmsEVM = hePlotEVMPerSymbol(eqDataSym,cfgRx,evmSymPlot,varargin)
|
||||||
|
% hePlotEVMPerSymbol Plots EVM per symbols for all spatial streams
|
||||||
|
%
|
||||||
|
% RMSEVM = hePlotEVMPerSymbol(EQDATASYM,CFGRX,EVMSYMPLOT) plots EVM per
|
||||||
|
% symbol averaged over subcarriers for all spatial streams.
|
||||||
|
%
|
||||||
|
% RMSEVM is the EVM of EQDATASYM in decibels.
|
||||||
|
%
|
||||||
|
% EQDATASYM are the demodulated HE-Data field OFDM symbols for a user,
|
||||||
|
% specified as a Nsd-by-Nsym-by-Nss matrix of real or complex values,
|
||||||
|
% where Nsd is the number of data subcarriers in the HE-Data field and
|
||||||
|
% Nsym is the number of OFDM symbols, and Nss is the number of spatial
|
||||||
|
% streams.
|
||||||
|
%
|
||||||
|
% CFGRX is the format configuration object of type <a href="matlab:help('wlanHERecoveryConfig')">wlanHERecoveryConfig</a>.
|
||||||
|
%
|
||||||
|
% EVMSYMPLOT is a system object of type <a href="matlab:help('dsp.ArrayPlot')">dsp.ArrayPlot</a>.
|
||||||
|
%
|
||||||
|
% RMSEVM = hePlotEVMPerSymbol(...,USERIDX,NUMUSERS) displays user
|
||||||
|
% number and number of user information in the figure title.
|
||||||
|
|
||||||
|
% Copyright 2019 The MathWorks, Inc.
|
||||||
|
|
||||||
|
[~,~,Nss] = size(eqDataSym);
|
||||||
|
|
||||||
|
if nargin == 5
|
||||||
|
userIdx = varargin{1};
|
||||||
|
numUsers = varargin{2};
|
||||||
|
elseif nargin == 4
|
||||||
|
userIdx = varargin{1};
|
||||||
|
numUsers = 1; % Number of users are unKnown, prefix this to 1
|
||||||
|
end
|
||||||
|
|
||||||
|
EVM = comm.EVM;
|
||||||
|
EVM.ReferenceSignalSource = 'Estimated from reference constellation';
|
||||||
|
EVM.ReferenceConstellation = wlanReferenceSymbols(cfgRx);
|
||||||
|
|
||||||
|
rmsEVMPerSym = permute(EVM(eqDataSym),[2 3 1]);
|
||||||
|
|
||||||
|
str = cell(Nss,1);
|
||||||
|
for iss=1:Nss
|
||||||
|
str{iss} = sprintf('Spatial stream %d',iss);
|
||||||
|
end
|
||||||
|
|
||||||
|
evmSymPlot.ChannelNames = str;
|
||||||
|
if nargin>3
|
||||||
|
evmSymPlot.Name = sprintf('EVM per symbol, user#%d/%d',userIdx,numUsers);
|
||||||
|
else
|
||||||
|
evmSymPlot.Name = sprintf('EVM per symbol');
|
||||||
|
end
|
||||||
|
|
||||||
|
rmsEVM = 20*log10(rmsEVMPerSym/100);
|
||||||
|
evmSymPlot(rmsEVM);
|
||||||
|
evmSymPlot.show
|
||||||
|
release(evmSymPlot);
|
||||||
|
|
||||||
|
end
|
91
heSIGBCommonFieldDecode.m
Normal file
91
heSIGBCommonFieldDecode.m
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
function [status,cfgRx,commonBits,eqCommonSym,failInterpretation] = heSIGBCommonFieldDecode(rx,chanEst,noiseVar,cfgRx,varargin)
|
||||||
|
%heSIGBCommonFieldDecode Decode HE-SIG-B common field
|
||||||
|
%
|
||||||
|
% [STATUS,CFGRX] = heSIGBCommonFieldDecode(RX,CHANEST,NOISEVAR,CFGRX)
|
||||||
|
% decode the HE-SIG-B common field given the HE-SIG-B common field
|
||||||
|
% samples, channel estimate, CHANEST, noise variance, NOISEVAR and
|
||||||
|
% recovery configuration object CFGRX.
|
||||||
|
%
|
||||||
|
% STATUS represents the result of content channel decoding, and is
|
||||||
|
% returned as a character vector. The STATUS output is determined by the
|
||||||
|
% combination of cyclic redundancy check (CRC) per content channel and
|
||||||
|
% the number of HE-SIG-B symbols signaled in HE-SIG-A field:
|
||||||
|
%
|
||||||
|
% Success - CRC passed for all content channels
|
||||||
|
% ContentChannel1CRCFail - CRC failed for content channel-1 and
|
||||||
|
% the number of HE-SIG-B symbols is less
|
||||||
|
% than 16.
|
||||||
|
% ContentChannel2CRCFail - CRC failed for content channel-2 and
|
||||||
|
% the number of HE-SIG-B symbols is less
|
||||||
|
% than 16.
|
||||||
|
% UnknownNumUsersContentChannel1 - CRC failed for content channel-1 and
|
||||||
|
% the number of HE-SIG-B symbols is
|
||||||
|
% equal to 16.
|
||||||
|
% UnknownNumUsersContentChannel2 - CRC failed for content channel-2 and
|
||||||
|
% the number of HE-SIG-B symbols is
|
||||||
|
% equal to 16.
|
||||||
|
% AllContentChannelCRCFail - CRC failed for all content channels.
|
||||||
|
%
|
||||||
|
% CFGRX is an updated format configuration object of type
|
||||||
|
% <a href="matlab:help('wlanHERecoveryConfig')">wlanHERecoveryConfig</a> after HE-SIG-B common field decoding.
|
||||||
|
%
|
||||||
|
% RX are the HE-SIG-B common field samples. The number of common field
|
||||||
|
% samples depends on the channel bandwidth as defined in Table 27-23 of
|
||||||
|
% IEEE P802.11ax/D4.1.
|
||||||
|
%
|
||||||
|
% CHANEST is a complex Nst-by-1-by-Nr array containing the estimated
|
||||||
|
% channel at data and pilot subcarriers, where Nst is the number of
|
||||||
|
% occupied subcarriers and Nr is the number of receive antennas.
|
||||||
|
%
|
||||||
|
% NOISEVAR is the noise variance estimate, specified as a nonnegative
|
||||||
|
% scalar.
|
||||||
|
%
|
||||||
|
% CFGRX is the format configuration object of type <a href="matlab:help('wlanHERecoveryConfig')">wlanHERecoveryConfig</a>
|
||||||
|
% and specifies the parameters for the HE-MU format.
|
||||||
|
%
|
||||||
|
% [...,FAILINTERPRETATION] = heSIGBCommonFieldDecode(...,SUPPRESSERROR)
|
||||||
|
% controls the behavior of the function due to an unexpected value of the
|
||||||
|
% interpreted HE-SIG-B common field bits. SUPPRESSERROR is logical. When
|
||||||
|
% SUPPRESSERROR is true and the function cannot interpret the recovered
|
||||||
|
% HE-SIG-B common field bits due to an unexpected value, the function
|
||||||
|
% returns FAILINTERPRETATION as true and cfgMU is unchanged. When
|
||||||
|
% SUPPRESSERROR is false and the function cannot interpret the recovered
|
||||||
|
% HE-SIG-B common field bits due to an unexpected value, an exception is
|
||||||
|
% issued, and the function does not return an output. The default is
|
||||||
|
% false.
|
||||||
|
|
||||||
|
% Copyright 2018-2020 The MathWorks, Inc.
|
||||||
|
|
||||||
|
suppressError = false; % Control the validation of the interpreted HE-SIG-B common field bits
|
||||||
|
failInterpretation = false;
|
||||||
|
if nargin>4
|
||||||
|
suppressError = varargin{1};
|
||||||
|
end
|
||||||
|
chanBW = cfgRx.ChannelBandwidth;
|
||||||
|
|
||||||
|
% Demodulate HE-SIG-B Common field
|
||||||
|
demodCommonSym = wlanHEDemodulate(rx,'HE-SIG-B',chanBW);
|
||||||
|
|
||||||
|
% Extract data and pilots symbols
|
||||||
|
preheInfo = wlanHEOFDMInfo('HE-SIG-A',chanBW);
|
||||||
|
demodCommonData = demodCommonSym(preheInfo.DataIndices,:,:);
|
||||||
|
demodCommonPilot = demodCommonSym(preheInfo.PilotIndices,:,:);
|
||||||
|
|
||||||
|
% Estimate and correct common phase error
|
||||||
|
demodCommonData = heCPECorrection(demodCommonData,demodCommonPilot,chanEst(preheInfo.PilotIndices,:,:),chanBW);
|
||||||
|
|
||||||
|
% Merge channels
|
||||||
|
[commonOne20MHz,chanEstOne20MHz] = heSIGBMergeSubchannels(demodCommonData,chanEst(preheInfo.DataIndices,:,:),chanBW);
|
||||||
|
|
||||||
|
% Perform equalization
|
||||||
|
[eqCommonSym,csiData] = preHESymbolEqualize(commonOne20MHz,chanEstOne20MHz,noiseVar);
|
||||||
|
|
||||||
|
% Decode HE-SIG-B common field
|
||||||
|
if suppressError
|
||||||
|
[commonBits,status] = wlanHESIGBCommonBitRecover(eqCommonSym,noiseVar,csiData,cfgRx);
|
||||||
|
[cfgRx,failInterpretation] = interpretHESIGBCommonBits(cfgRx,commonBits,status);
|
||||||
|
else
|
||||||
|
[commonBits,status,cfgRx] = wlanHESIGBCommonBitRecover(eqCommonSym,noiseVar,csiData,cfgRx);
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user