主要内容

ofdmChannelEstimate

Perform OFDM channel estimation based on pilot locations and pilot symbols

Since R2026a

Description

[h,nVar] = ofdmChannelEstimate(rxSym,pilotcfg,cplen) performs the OFDM channel estimation based on pilot locations and pilot symbols specified by OFDM pilot configuration object, pilotcfg.

[h,nVar] = ofdmChannelEstimate(rxSym,pilotcfg,cplen,Algorithm=algorithm) allows you to choose the channel estimation algorithm using an optional name-value argument. For more information, see Algorithms.

example

Examples

collapse all

Estimate the wireless channel in a MIMO OFDM system using pilot signals.

Set up top level parameters.

numStreams = 2;  % Number of data streams (Ns)
numTx = 4;       % Number of transmit antennas (Nt)
numRx = 3;       % Number of receive antennas (Nr)
nfft = 64;       % FFT length
cpLen = 16;      % Cyclic prefix length
numOFDMSym = 10; % Number of OFDM symbols
bps = 6;         % Bits per OFDM data subcarrier
M = 2^bps;       % Modulation order
numGuardBandCarriers1 = 6;
numGuardBandCarriers2 = 5;
fc = 1e9;
lambda = physconst('LightSpeed')/fc;
beamAngles = 15;

Set up the active data subcarriers excluding the following values:

  • Left guard band (1:numGuardBandCarriers1)

  • DC (nfft/2+1)

  • Right guard band (nfft-numGuardBandCarriers2+1:nfft).

dataIdx = [numGuardBandCarriers1+1:nfft/2 nfft/2+2:nfft-numGuardBandCarriers2]; % Skip DC subcarrier at nfft/2+1
numDataSC = numel(dataIdx); % count of active subcarriers
antIdx = (0:numTx-1); % antenna index vector [0,1,...,Nt-1]
antDelay = 2*pi*sin(2*pi*beamAngles*(0:numStreams-1).'/360)/lambda;
B = exp(1i*antIdx.*antDelay);  % Ns x Nt beamformer matrix
SNRdB = 40;
numFrames = 500;
rng(123); % Fix random seed

Create the OFDM pilot configuration object.

pilotcfg = ofdmPilotConfig(FFTLength = nfft, ...
    NumGuardBandCarriers = [numGuardBandCarriers1 ; numGuardBandCarriers2], ...
    NumSymbols = numOFDMSym, ...
    NumTransmitStreams = numStreams, ...
    StreamGroups = {1:numStreams});

Pick pilot locations and orthogonal vectors for pilot symbols. Validate the pilot configuration and plot it.

pilotcfg.PilotLocations = {ofdmPilotGrid([1 2], 1, dataIdx(1:2:end), ...
                           [1 numOFDMSym])};
pilotcfg.PilotSymbols = cellfun(@(x) reshape(pskmod(randi([0 3], ...
              size(x,1)*size(x,3),1),4,pi/4), ...
              size(x,1),1,size(x,3)) .* ... % Random QPSK symbols
              (size(x,1)*ifft(eye(size(x,1)))), ...   % Orthogonal vectors
               pilotcfg.PilotLocations, 'UniformOutput', false);
validate(pilotcfg);
plot(pilotcfg);

Insert pilot symbols.

[pilotsym, pilotind] = pilotSignal(pilotcfg);
txGrid = zeros(pilotcfg.FFTLength - sum(pilotcfg.NumGuardBandCarriers), pilotcfg.NumSymbols, pilotcfg.NumTransmitStreams);
txGrid(pilotind) = pilotsym;

Set up the MIMO channel.

mimoChannel = comm.MIMOChannel( ...
    SampleRate=1e6, ...
    PathDelays=[0 3e-7 5e-7], ...
    AveragePathGains=[0 -2 -3], ...
    MaximumDopplerShift=20, ...
    SpatialCorrelationSpecification="None", ...
    NumTransmitAntennas=numTx, ...
    NumReceiveAntennas=numRx);

Account for the timing offset and symbol offset, remove the initial samples, and then pad with zeros to keep the signal length unchanged.

mimoChannelInfo = info(mimoChannel);
toffset = mimoChannelInfo.ChannelFilterDelay;
zeropadding = zeros(toffset,numRx);

Set up the constellation diagram.

constdiag = comm.ConstellationDiagram(Title = 'Equalized by output of ofdmChannelEstimate',...
ReferenceConstellation = qammod(0:M-1,M,UnitAveragePower=true),...
EnableMeasurements = true, Position = [100 100 800 800]);

Generate random data bits and the QAM output.

for count = 1:numFrames
    dataBits = randi([0,1],[numDataSC*bps numOFDMSym-2 numStreams]);
    qamTx = qammod(dataBits,M,InputType="bit",UnitAveragePower=true);
    txGrid(dataIdx - numGuardBandCarriers1,2:end-1,:) = qamTx; % No data in the first and the last OFDM symbols
  % Perform OFDM modulation and apply beamforming.
    ofdmOut = ofdmmod(txGrid,nfft,cpLen,[1:numGuardBandCarriers1 nfft-numGuardBandCarriers2+1:nfft]');
    txOut = ofdmOut * B;
  % Pass through the MIMO channel and add noise using an AWGN channel
    channelOut = mimoChannel(txOut);
    rxIn = awgn(channelOut,SNRdB,"measured"); % add noise
  % Perform OFDM demodulation and extract the data subcarriers.
    ofdmDemodIn = [rxIn(toffset+1:end,:); zeropadding];
    rxFullGrid = ofdmdemod(ofdmDemodIn,nfft,cpLen,cpLen/2); % Use cpLen/2 for symbol sampling offset
    rxSym = rxFullGrid(dataIdx,:,:);
  % Perform channel estimation from the pilots.
    r = rxFullGrid((numGuardBandCarriers1+1:nfft-numGuardBandCarriers2),:,:);
    [hEst, nVarEst] = ofdmChannelEstimate(r, pilotcfg, cpLen);
  % Use hEst from ofdmChannelEstimate to equalize the received signal.
    dcIndx = nfft/2+1-numGuardBandCarriers1; % DC index for hEst
    hPractical = reshape(hEst([1:dcIndx-1 dcIndx+1:end],:,:,:),[],numStreams,numRx);
    eqSym = ofdmEqualize(rxSym,hPractical,nVarEst);
  % Plot a constellation diagrams of the equalized data symbols.
constdiag(reshape(eqSym(:,2:(numOFDMSym-1),:),[],1));
end

Input Arguments

collapse all

Received symbols, specified as a 3-D array where the:

  • First dimension represents the number of active subcarriers. The value must be equal to fftlength – the total number of subcarriers in the guard bands.

  • Second dimension represents is the number of OFDM symbols specified by NumSymbols.

  • Third dimension represents the number of receive antennas.

Consider an OFDM system with 64 subcarriers, 10 OFDM symbols, and 3 receive antennas. After OFDM modulation, the receiver collects the signal for every subcarrier, every symbol, and every antenna. The rxSig is a 64-by-10-by-3 array.

Data Types: double | single
Complex Number Support: Yes

Pilot configuration object, specified as an ofdmPilotConfig object.

Cyclic prefix length, specified as a positive scalar integer.

Data Types: double

Algorithm for channel estimation, specified as 'leastsquares-with-denoising' or 'leastsquares'. For more information, see Algorithms.

Data Types: char | string

Output Arguments

collapse all

Channel estimate, returned as a 4-D array of the same data type as rxSig where the:

  • First dimension is the number of active subcarriers and is equal to the first dimension of rxSig.

  • Second dimension is the number of OFDM symbols.

  • Third dimension is the number of transmit streams.

  • Fourth dimension is the number of receive antennas and is equal to the third dimension of rxSig.

Data Types: double | single
Complex Number Support: Yes

Noise variance estimate, returned as scalar.

Data Types: single

Algorithms

collapse all

Extended Capabilities

expand all

C/C++ Code Generation
Generate C and C++ code using MATLAB® Coder™.

Version History

Introduced in R2026a

See Also

Functions

Objects

Blocks