function [numPacketErrors, numPacketsSimulated, cfrMagnitudes, rxPower, pathLoss]= simulateTransmission(accessAnalysisParameters, cfgEHT, channel, maxChDelay, snr, maxNumErrors, simParameters) numPacketErrors = 0; numPacketsSimulated = 0; cfrMagnitudes = []; rxPower = zeros(size(accessAnalysisParameters.elevationAngles)); pathLoss = zeros(size(accessAnalysisParameters.elevationAngles)); ofdmInfo = wlanEHTOFDMInfo('EHT-Data', cfgEHT); ind = wlanFieldIndices(cfgEHT); stream = RandStream('combRecursive', Seed=simParameters.Seed); stream.Substream = 1; RandStream.setGlobalStream(stream); powerOnlySimulation = isempty(snr); if ~powerOnlySimulation snrVal = convertSNR(snr, "snrsc", "snr", FFTLength=ofdmInfo.FFTLength, NumActiveSubcarriers=ofdmInfo.NumTones); end if isfield(simParameters, 'TransmitPower') txPower = simParameters.TransmitPower; else txPower = 20; end lambda = physconst("lightspeed") / simParameters.CarrierFrequency; includePathLoss = isfield(simParameters, 'IncludeFreeSpacePathLoss') && simParameters.IncludeFreeSpacePathLoss; while (powerOnlySimulation || numPacketErrors < maxNumErrors) && numPacketsSimulated < numel(accessAnalysisParameters.elevationAngles) numPacketsSimulated = numPacketsSimulated + 1; if includePathLoss packetDistance = accessAnalysisParameters.distances(numPacketsSimulated); pathLoss(numPacketsSimulated) = 20 * log10(4 * pi * packetDistance / lambda); else pathLoss(numPacketsSimulated) = 0; end rxPower(numPacketsSimulated) = txPower - pathLoss(numPacketsSimulated); txPSDU = randi([0 1], psduLength(cfgEHT) * 8, 1); tx = wlanWaveformGenerator(txPSDU, cfgEHT); stf = tx(ind.LSTF(1):ind.LSTF(2), :); stfPower = mean(abs(stf(:)).^2); tx = tx * sqrt(10^((txPower - 30) / 10)) / sqrt(stfPower); packetElevationAngle = accessAnalysisParameters.elevationAngles(numPacketsSimulated); if isfield(accessAnalysisParameters, "dopplerShifts") && isfinite(accessAnalysisParameters.dopplerShifts(numPacketsSimulated)) packetDopplerShift = accessAnalysisParameters.dopplerShifts(numPacketsSimulated); else packetDopplerShift = dopplerShiftCircularOrbit(packetElevationAngle, simParameters.SatelliteAltitude, simParameters.MobileAltitude, simParameters.CarrierFrequency); end if ~isfinite(packetDopplerShift) packetDopplerShift = 0; end channel.SatelliteDopplerShift = packetDopplerShift; txPad = [tx; zeros(maxChDelay, cfgEHT.NumTransmitAntennas)]; if isfield(accessAnalysisParameters, "preCompensation") predictedDopplerShift = []; if isnumeric(accessAnalysisParameters.preCompensation) predictedDopplerShift = packetDopplerShift + accessAnalysisParameters.preCompensation; elseif string(accessAnalysisParameters.preCompensation) == "ideal" predictedDopplerShift = packetDopplerShift; end if ~isempty(predictedDopplerShift) && isfinite(predictedDopplerShift) txPad = frequencyOffset(txPad, simParameters.SampleRate, -predictedDopplerShift); end end if powerOnlySimulation continue; end reset(channel); rx = awgn(channel(txPad) * db2mag(-pathLoss(numPacketsSimulated)), snrVal); coarsePacketOffset = wlanPacketDetect(rx, cfgEHT.ChannelBandwidth); if isempty(coarsePacketOffset) numPacketErrors = numPacketErrors + 1; continue; end lstf = rx(coarsePacketOffset + (ind.LSTF(1) : ind.LSTF(2)), :); coarseFrequencyOffset = wlanCoarseCFOEstimate(lstf, cfgEHT.ChannelBandwidth); rx = frequencyOffset(rx, simParameters.SampleRate, -coarseFrequencyOffset); nonhtfields = rx(coarsePacketOffset + (ind.LSTF(1) : ind.LSIG(2)), :); finePacketOffset = wlanSymbolTimingEstimate(nonhtfields, cfgEHT.ChannelBandwidth); packetOffset = coarsePacketOffset + finePacketOffset; if packetOffset > maxChDelay numPacketErrors = numPacketErrors + 1; continue; end rxLLTF = rx(packetOffset + (ind.LLTF(1) : ind.LLTF(2)), :); fineFrequencyOffset = wlanFineCFOEstimate(rxLLTF, cfgEHT.ChannelBandwidth); rx = frequencyOffset(rx, simParameters.SampleRate, -fineFrequencyOffset); rxHELTF = rx(packetOffset + (ind.EHTLTF(1) : ind.EHTLTF(2)), :); heltfDemod = wlanEHTDemodulate(rxHELTF, "EHT-LTF", cfgEHT); [chanEstimate, pilotEstimate] = wlanEHTLTFChannelEstimate(heltfDemod, cfgEHT); cfrMagnitudes(:, end + 1) = abs(chanEstimate(:, 1, 1)); rxData = rx(packetOffset + (ind.EHTData(1) : ind.EHTData(2)), :); demodSym = wlanEHTDemodulate(rxData, "EHT-Data", cfgEHT); if ~isfield(accessAnalysisParameters, "enablePilotTracking") || accessAnalysisParameters.enablePilotTracking demodSym = wlanEHTTrackPilotError(demodSym, chanEstimate, cfgEHT, "EHT-Data"); end nVarEst = wlanEHTDataNoiseEstimate(demodSym(ofdmInfo.PilotIndices, :, :),pilotEstimate, cfgEHT); demodDataSym = demodSym(ofdmInfo.DataIndices, :, :); chanEstimateData = chanEstimate(ofdmInfo.DataIndices, :, :); [eqSym, csi] = wlanEHTEqualize(demodDataSym, chanEstimateData, nVarEst, cfgEHT, 'EHT-Data'); rxPSDU = wlanEHTDataBitRecover(eqSym, nVarEst, csi, cfgEHT); numPacketErrors = numPacketErrors + any(biterr(txPSDU, rxPSDU)); end end