新建
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