仅本人记录,代码如下(仿真结果在最后)
function [BER,BLER]=OTFS(velocity_kmph,snrRange,simIterations)
%输入速度(km/h; 信噪比; 迭代次数)
%% %%%%%%%%%%%%%%%%%%%%%%% INPUT PARAMETERS %%%%%%%%%%%%%%%%%%%%%%% %%
% System Parameters系统参数
nSymbolsPerBlock = 32; % Number of symbols per frame
fSubcarrierSpacing = 62.5e3; % SC spacing in Hz
nFft = 128; % FFT size
nCyclicPrefix = floor(nFft * 0.067); % CP length in samples (6.7% is the calibration assumption defined in 3GPP R1-165989)
samplingRate = nFft * fSubcarrierSpacing; % Sampling rate
modOrder = 4; % 4 for QPSK, 16 for 16QAM, 64 for 64QAM, 256 for 256QAM
nTxAntennas = 1;
nRxAntennas = 1;
nSubcarriers = nFft;
nBitsPerBlock = nSymbolsPerBlock * nSubcarriers * log2(modOrder);
% Parameter for LTE Channel Coder LTE信道编码参数
turboDecodingNumIterations = 8;
codeRate = 0.5; % Coding rate of source data bits over transmition redundant data bits
codedTransportBlockSize = nBitsPerBlock * codeRate;
crcBitLength = 24; % defined in 3GPP TS36.2xx
maxCodeBlockSize = 6144; % defined in 3GPP TS36.2xx
numCodeBlockSegments = ceil((codedTransportBlockSize - crcBitLength) / maxCodeBlockSize);
if numCodeBlockSegments > 1
tbs = codedTransportBlockSize-crcBitLength*(numCodeBlockSegments+1); % CRC24A + CRC24B*numSegments
else
tbs = codedTransportBlockSize-crcBitLength; % CRC24A only
end
% Parameters for Scrambler 加扰参数
rnti = hex2dec('003D');
cellId = 0;
frameNo = 0; % radio frame
codeword = 0;
% Parameter for OFDM Modulator OFDM调制参数
nGuardBands = [(nFft - nSubcarriers)/2; (nFft - nSubcarriers)/2];
% Number of guard band subcarriers in both sides 两侧保护带子载波数
% Parameter for ChannelEstimator 信道估计参数
activeSubcarrierIndices = 1+nGuardBands(1):nFft-nGuardBands(2);
% Parameters for Fading Channel 衰落信道参数
delaySpread_ns = 300; % rms delay spred for TDL channel model only, in nano second
%仅适用于 TDL 通道模型的 rms 延迟扩展,以纳秒为单位
fCenter = 4e9; % center carrier frequency [Hz]
velocity = velocity_kmph*1000/(60*60); % convert km/h -> m/s
waveLength = physconst('lightspeed')/fCenter;
fDoppler = velocity / waveLength;
txCorrMat = 1;
rxCorrMat = 1;
%% %%%%%%%%%%%%%%%%%%%%%%% ALGORITHM SELECTION 算法选择%%%%%%%%%%%%%%%%%%%%%%% %%
% ----- Path Estimator 信道估计 -----
%channelEstimationAlgorithm = 'Pilot-based iterative path estimation'; %导频迭代估计
%channelEstimationAlgorithm = 'PN-based iterative estimation'; %PN序列估计
channelEstimationAlgorithm = 'Ideal'; %理想信道估计
fprintf('Channel estimation: %s\n', channelEstimationAlgorithm);
% ----- Equalizer 均衡 -----
equalizerAlgorithm = 'Vectorized equalizer';
eqAlgorithm = 'blockedMMSE'; %MMSE均衡
% equalizerAlgorithm = 'Deconvolutional equalizer';
% eqAlgorithm = 'Wiener';
fprintf('Channel equalization: %s\n', equalizerAlgorithm);
% ----- Channel -----
channelModel = 'EVA';
fprintf('Channel profile: %s\n', channelModel);
%---- Channel Coding ----
channelCoding = 'LTE';
% channelCoding = 'None';
fprintf('Channel coding: %s\n', channelCoding);
%% %%%%%%%%%%%%%%%%%%%%%%% OBJECT GENERATION 目标生成 %%%%%%%%%%%%%%%%%%%%%%% %%
switch channelCoding
case 'None'
% Bit Generator
hBitGenerator = RandomBitGenerator('DataLength', nBitsPerBlock);
% Symbol Mapper
hSymbolMapper = QamMapperV2( ...
'ModOrder', modOrder, ...
'InputType', 'bit', ...
'OutputType', 'bit', ... % 'bit' for uncoded, 'llr' for coded
'UnitAveragePower', true, ...
'LLROverflowPrevention', true);
case 'LTE'
% Bit Generator
hBitGenerator = RandomBitGenerator('DataLength', tbs);
% Symbol Mapper
hSymbolMapper = QamMapperV2( ...
'ModOrder', modOrder, ...
'InputType', 'bit', ...
'OutputType', 'llr', ... % 'bit' for uncoded, 'llr' for coded
'UnitAveragePower', true, ...
'LLROverflowPrevention', true);
% Symbol Mapper for uncoded
hSymbolMapperUncoded = QamMapperV2( ...
'ModOrder', modOrder, ...
'InputType', 'bit', ...
'OutputType', 'bit', ... % 'bit' for uncoded, 'llr' for coded
'UnitAveragePower', true, ...
'LLROverflowPrevention', true);
% LTE Channel Coder
hChannelCoder = LteChannelCoder( ...
'TurboDecodingNumIterations', turboDecodingNumIterations, ...
'ModOrder', modOrder, ...
'NumLayers', 1, ...
'OutputLength', nBitsPerBlock, ...
'LinkDirection', 'Downlink', ...
'RedundancyVersion', 0, ...
'TBS', tbs);
% Scrambler
hScrambler = LteScrambler(rnti, cellId, frameNo, codeword);
end
% OFDM Modulator OFDM调制
hOfdmModulator = CpOfdmModulator(...
'FFTLength', nFft, ...
'NumGuardBandCarriers', nGuardBands, ...
'NumSymbols', nSymbolsPerBlock, ...
'CyclicPrefixLength', nCyclicPrefix, ...
'InsertDCNull', false, ...
'PilotInputPort', false, ...
'PilotOutputPort', false, ...
'NumTransmitAntennas', nTxAntennas, ...
'NumReceiveAntennas', nRxAntennas, ...
'SubcarrierIndexOrder', 'ZeroToFFTSize');
% OTFS Precoder OTFS预编码
hPrecoder = OtfsPrecoder( ...
'NumDelayBins', nSubcarriers, ...
'NumDopplerBins', nSymbolsPerBlock, ...
'NumTransmitAntennas', nTxAntennas, ...
'NumReceiveAntennas', nRxAntennas);
% Path Estimator 信道估计
switch channelEstimationAlgorithm
case 'Pilot-based iterative path estimation'
hEstimator = OtfsPilotResponseBasedPathParameterEstimator( ...
'DividingNumber', 10, ...
'CyclicPrefixLength', nCyclicPrefix, ... % Ncp
'NumDopplerBins', nSymbolsPerBlock, ... % N
'NumDelayBins', nSubcarriers, ... % M
'SamplingRate', samplingRate ...
);
threshAlpha = 1/50;
threshBeta = 1/10;
localUpdateThreshold = 0.01;
case 'PN-based iterative estimation'
% threshold = 1/150; % This is the best performance regardless the computation time
threshold = 1/25; % This is the same number of paths to be estimated with the proposed CE
hEstimator = OtfsPNSeqBasedPathParameterEstimator( ...
'DividingNumber', 10, ...
'CyclicPrefixLength', nCyclicPrefix, ... % Ncp
'NumDopplerBins', nSymbolsPerBlock, ... % N
'NumDelayBins', nSubcarriers, ... % M
'SamplingRate', samplingRate, ...
'Threshold', threshold);
case 'Ideal'
end
% OTFS Equalizer OTFS均衡
switch equalizerAlgorithm
case 'Deconvolutional equalizer'
hEqualizer = OtfsDeconvolutionalEqualizer( ...
'NumSymbols', nSymbolsPerBlock, ... % N
'CyclicPrefixLength', nCyclicPrefix, ... % Ncp
'NumSubcarriers', nSubcarriers, ... % M
'SamplingRate', samplingRate, ...
'DividingNumber', 10, ...
'EqualizationAlgorithm', eqAlgorithm);
case 'Vectorized equalizer'
hEqualizer = OtfsVectorizedEqualizer( ...
'EqualizationAlgorithm', 'MMSE', ...
'NumSymbols', nSymbolsPerBlock, ... % N
'CyclicPrefixLength', nCyclicPrefix, ... % Ncp
'NumSubcarriers', nSubcarriers, ... % M
'SamplingRate', samplingRate, ...
'OutputConditionNumber', false, ...
'EqualizationAlgorithm', eqAlgorithm);
end
% Fading Channel 衰落信道
hFading = SoSBasedChannel( ... % based on in-house implementation
'ChannelModel', channelModel, ...
'RMSDelaySpread', delaySpread_ns, ...
'SamplingRate', samplingRate, ...
'DopplerFrequency', fDoppler, ...
'NumTxAntennas', nTxAntennas, ...
'NumRxAntennas', nRxAntennas, ...
'TxCorrMatrix', txCorrMat, ...
'RxCorrMatrix', rxCorrMat, ...
'OutputCIR', true, ...
'CyclicPrefix', nCyclicPrefix, ...
'FFTSize', nFft, ...
'ImpulseSource', 'Input', ...
'SequentialOrRandomChannel', 'Sequential', ...
'FDFMethod', 'ApplyFDFToPathParameters');
% AWGN 高斯白噪声
hAwgn = AwgnChannel('N0');
%% %%%%%%%%%%%%%%%%%%%%%%% SIMULATION SETTINGS 仿真设置 %%%%%%%%%%%%%%%%%%%%%%% %%
% Create an empty storage to store simulation status创建一个空存储来存储模拟状态
simstatus = table; % use table-type variable since it's good to see in the workspace 使用表类型变量,因为在工作区中可以看到
simstatus.SNR = snrRange';
simstatus.BER = nan * zeros(length(snrRange),1);
simstatus.UncodedBER = nan * zeros(length(snrRange),1);
simstatus.BLER = nan * zeros(length(snrRange),1);
simstatus.TotalBitErrors = zeros(length(snrRange),1);
simstatus.TotalUncodedBitErrors = zeros(length(snrRange),1);
simstatus.TotalBlockErrors = zeros(length(snrRange),1);
simstatus.Iteration = zeros(length(snrRange),1);
simstatus.PathCounts = zeros(length(snrRange),1);
simstatus.ComputeTime = zeros(length(snrRange),1);
%% %%%%%%%%%%%%%%%%%%%%%%% START SIMULATION 开始仿真%%%%%%%%%%%%%%%%%%%%%%% %%
% For ideal channel estimation 对于理想信道估计
delayDopplerImpulse = zeros(nSubcarriers, nSymbolsPerBlock);
delayDopplerImpulse(1,1)=sqrt(nSymbolsPerBlock*nSubcarriers);
ddImpulseInTFDomain = hPrecoder.encode(delayDopplerImpulse);
ddImpulseInTimeDomain = hOfdmModulator.modulate(ddImpulseInTFDomain);
% For PN-sequence based channel estimation PN序列估计
switch channelEstimationAlgorithm
case {'PN-based estimation'}
txPNSeq = zeros((nCyclicPrefix+nFft)*nSymbolsPerBlock*10,1); % for long PN sequence
% txPNSeq = zeros((nCyclicPrefix+nFft)*nSymbolsPerBlock*1,1); % for short PN sequence
nPNSeq = 1023;
tmpSeq = repmat(genltegoldseq(nPNSeq, de2bi(31,31)), 1, ceil(length(txPNSeq)/nPNSeq));
% 1023-length with an initial value of 31
tmpSeq(tmpSeq==0) = -1; % map 0 or 1 bit into -1 or 1 bit
txPNSeq = tmpSeq(1:length(txPNSeq))';
case 'PN-based iterative estimation'
txPNSeq = zeros((nCyclicPrefix+nFft)*nSymbolsPerBlock,1);
nPNSeq = 1023;
tmpSeq = repmat(genltegoldseq(nPNSeq, de2bi(31,31)), 1, ceil(length(txPNSeq)/nPNSeq)); % 1023-length with an initial value of 31 1023 长度,初始值为 31
tmpSeq(tmpSeq==0) = -1; % map 0 or 1 bit into -1 or 1 bit
txPNSeq = tmpSeq(1:length(txPNSeq))';
end
charCount = 49+17;
for snrdb = snrRange
rng('default');
rng(106);
fprintf('\nSNR = %2d dB \n', snrdb);
snrIndex = find(snrRange==snrdb);
snr = 10^(snrdb/10);
noiseVar = 1/snr; % Total power
N0 = noiseVar/nFft; % N0 is the power spectral density of noise per unit of bandwidth, which is band-limited.
%N0 是每单位带宽的噪声功率谱密度,它是带限的。
fprintf(repmat(' ', 1, charCount)); % Print spaces in advance to avoid deleting the previously displayed characters
%提前打印空格,避免删除之前显示的字符
tic %tic用来保存当前时间,而后使用toc来记录程序完成时间
numBitErrors=[];
numBitErrorsU=[];
blockError2=[];
for count = 1:simIterations(snrIndex)
%% Transmitter 发射端
% Bit Generation 符号生成
txBits = hBitGenerator.generate();
% txBits = zeros(size(txBits)); % FOR TEST
switch channelCoding
case 'None'
txScrampledBits = txBits;
case 'LTE'
% Channel Encoding 信道编码
txCodedBits = hChannelCoder.encode(txBits);
% Scrambler 加扰
txScrampledBits = hScrambler.scramble(txCodedBits);
end
txScrampledBitsLen(count)=length(txScrampledBits);
% Symbol Mapping (QAM modulation) QAM调制
txSymbols = hSymbolMapper.map(txScrampledBits);
% OTFS Modulation OTFS调制
txBlocks = reshape(txSymbols, nSubcarriers, nSymbolsPerBlock);
txPrecodedBlocks = hPrecoder.encode(txBlocks);
% OFDM Modulation OFDM调制
txSignals = hOfdmModulator.modulate(txPrecodedBlocks);
%% Channel信道
% Fading Channel 衰落信道
switch channelEstimationAlgorithm
case {'Pilot-based iterative path estimation', 'Ideal'}
hFading.initRayleighFading();
[distortedSignals, cir] = hFading.apply(txSignals, ddImpulseInTimeDomain);
case 'PN-based iterative estimation'
[distortedSignals, distortedPNSeq] = hFading.apply(txSignals, txPNSeq);
end
% AWGN Channel 高斯白噪声信道
[noisySignals, ~] = hAwgn.add(distortedSignals, N0);
%% Receiver接收端
% OFDM Demodulator OFDM解调
rxPrecodedBlocks = hOfdmModulator.demodulate(noisySignals(1:(nFft+nCyclicPrefix)*nSymbolsPerBlock));
% OTFS Demodulator OTFS解调
rxBlocks = hPrecoder.decode(rxPrecodedBlocks);
% Equalization (Ideal) 均衡
switch channelEstimationAlgorithm
case 'Pilot-based iterative path estimation'
noisyCir = hAwgn.add(cir, N0);
chanEst = hPrecoder.decode(hOfdmModulator.demodulate(noisyCir(1:(nFft+nCyclicPrefix)*nSymbolsPerBlock)));
[estGains, estDopplers, estDelays, estOffsets] = hEstimator.estimate(chanEst, threshAlpha, threshBeta, noiseVar); rxEqBlocks = hEqualizer.equalize(rxBlocks, estGains, estDopplers, estDelays, estOffsets, noiseVar, localUpdateThreshold);
case 'PN-based iterative estimation'
noisyPNSeq = hAwgn.add(distortedPNSeq, noiseVar*sqrt(nSubcarriers));
[estGains, estDopplers, estDelays, estOffsets] = hEstimator.estimateIteratively(noisyPNSeq, txPNSeq, fDoppler*2);
rxEqBlocks = hEqualizer.equalize(rxBlocks, estGains, estDopplers, estDelays, estOffsets, noiseVar, 0.01);
case 'Ideal'
chanEst = hPrecoder.decode(hOfdmModulator.demodulate(cir(1:(nFft+nCyclicPrefix)*nSymbolsPerBlock)));
idealGains = hFading.pathRayleighGains;
idealDopplers = hFading.pathDopplers;
idealDelays = hFading.pathDelays;
idealOffsets = hFading.pathOffsets;
rxEqBlocks = hEqualizer.equalize(rxBlocks, idealGains, idealDopplers, idealDelays, idealOffsets, noiseVar);
end
rxSymbols = rxEqBlocks(:);
% Symbol Demapping 符号解映射
rxSoftBits = hSymbolMapper.demap(rxSymbols, noiseVar);
% Channel Decoding 信道解码
switch channelCoding
case 'None'
rxUncodedHardBits = rxSoftBits;
rxHardBits = rxUncodedHardBits;
if sum(xor(txBits, rxHardBits)) > 0
blockError = 1;
else
blockError = 0;
end
case 'LTE'
rxUncodedHardBits = hSymbolMapperUncoded.demap(rxSymbols);
% Descrambling 解扰
rxDescrambledBits = hScrambler.descramble(rxSoftBits);
[rxHardBits, blockError] = hChannelCoder.decode(rxDescrambledBits);
end
% Bit Error Rate 计算误码率
numBitErrors(count) = sum(xor(txBits, rxHardBits));
numBitErrorsU(count)= sum(xor(txScrampledBits, rxUncodedHardBits));
blockError2(count)=blockError;
end
simstatus.TotalBitErrors(snrIndex) = sum(numBitErrors);
simstatus.BER(snrIndex) = simstatus.TotalBitErrors(snrIndex)/(simIterations(snrIndex)*nBitsPerBlock);
simstatus.TotalBlockErrors(snrIndex) = simstatus.TotalBlockErrors(snrIndex) + sum(blockError2);
simstatus.BLER(snrIndex) = simstatus.TotalBlockErrors(snrIndex)/simIterations(snrIndex);
simstatus.TotalUncodedBitErrors(snrIndex) = sum(numBitErrorsU);
simstatus.UncodedBER(snrIndex) = simstatus.TotalUncodedBitErrors(snrIndex)/(simIterations(snrIndex)*txScrampledBitsLen(1));
fprintf('[%5d /%5d] BLER: %1.4f, BER: %1.7f (%9d/ %9d)', simIterations(snrIndex), simIterations(snrIndex), simstatus.BLER(snrIndex), simstatus.UncodedBER(snrIndex), simstatus.TotalUncodedBitErrors(snrIndex), simIterations(snrIndex)*txScrampledBitsLen(1));
computationTime = toc;
computationTimePerIteration = computationTime/simIterations(snrIndex);
fprintf(' Computation Time : %f sec. (as per iteration)\n', computationTimePerIteration);
simstatus.ComputeTime(snrIndex) = computationTimePerIteration;
end
BER=simstatus.BER;
BLER=simstatus.BLER;
%% %%%%%%%%%%%%%%%%%%%%%%% function END %%%%%%%%%%%%%%%%%%%%%%% %%
end