Main Content

ofdmdemod

Demodulate using OFDM method

Description

Y = ofdmdemod(X,nfft,cplen) demodulates the input time domain signal specified in X using the orthogonal frequency division multiplexing (OFDM) method with an FFT size specified by nfft and cyclic prefix length specified by cplen. For information, see OFDM Demodulation.

example

Y = ofdmdemod(X,nfft,cplen,symOffset) applies the symbol sampling offset, symOffset, for each OFDM symbol before demodulation of the input.

Y = ofdmdemod(X,nfft,cplen,symOffset,nullidx) removes null subcarriers from the locations specified in nullidx. For this syntax, the symbol sampling offset is applied to each OFDM symbol and the number of rows in the output is nfftlength(nullidx), which accounts for the removal of null subcarriers. Use null subcarriers to account for guard bands and DC subcarriers. For information, see Subcarrier Allocation and Guard Bands.

example

[Y,pilots] = ofdmdemod(X,nfft,cplen,symOffset,nullidx,pilotidx) returns pilot subcarriers for the pilot indices specified in pilotidx. For this syntax, the symbol sampling offset is applied to each OFDM symbol and number of rows in the output Y is nfftlength(nullidx)length(pilotidx), which accounts for the removal of null and pilot subcarriers. The function assumes that pilot subcarrier locations are the same across each OFDM symbol and transmit stream.

example

Y = ofdmdemod(X,nfft,cplen,___,OversamplingFactor=Value) specifies the optional oversampling factor name-value argument in addition to input arguments in previous syntaxes. The oversampling factor for an upsampled input signal must be specified as a positive scalar, and the products (OversamplingFactor×nfft) and (OversamplingFactor×cplen) must both result in integers. The default value for OversamplingFactor is 1.

For example, ofdmdemod(inSym,nfft,cplen,OversamplingFactor=2) demodulates assuming the input signal was upsampled by a factor of two.

Tip

If you set the oversampling factor to a noninteger rational number, specify a fractional value rather than a decimal value. For example, with an FFT length of 12 and an oversampling factor of 4/3, their product is the integer 16. However, rounding 4/3 to 1.333 when setting the oversampling factor results in a noninteger product of 15.9960, which results in a code error.

example

Examples

collapse all

OFDM-demodulate a signal with different CP lengths for different symbols.

Initialize input parameters defining locations for null and pilot subcarriers. Generate random data and perform OFDM modulation.

M = 16;
nfft = 64;
cplen = [16 32];
nSym = 2;
dataSym = randi([0 M-1],nfft,nSym);
qamSig = qammod(dataSym,M,UnitAveragePower=true);
y1 = ofdmmod(qamSig,nfft,cplen);

Demodulate the OFDM symbols. Compare the results to the original input data. The difference between the signals is negligible.

x1 = ofdmdemod(y1,nfft,cplen);
rxData = qamdemod(x1,M,UnitAveragePower=true);
isequal(rxData,dataSym)
ans = logical
   1

Apply OFDM multiplexing to a 16-QAM signal filtered by a SISO link with Rayleigh fading.

Initialize simulation variables, and create Rayleigh fading channel and constellation diagram objects.

s1 = RandStream('mt19937ar',Seed=12345);
nFFT = 64;
cpLen = 16;
nullIdx = [1:6 33 64-4:64].';
numTones = nFFT-length(nullIdx);

k = 4; % bits per symbol
M = 2^k;
constSym = qammod((0:M-1),M, ...
    UnitAveragePower=true); % reference constellation symbols

maxDopp = 1;
pathDelays = [0 4e-3 8e-3];
pathGains = [0 -2 -3];
sRate = 1000;
sampIdx = round(pathDelays/(1/sRate)) + 1;

chan = comm.RayleighChannel(PathGainsOutputPort=true, ...
    MaximumDopplerShift=maxDopp, ...
    PathDelays=pathDelays, ...
    AveragePathGains=pathGains, ...
    SampleRate=sRate, ...
    RandomStream='mt19937ar with seed');

cdScope = comm.ConstellationDiagram( ...
    ShowReferenceConstellation=true, ...
    ReferenceConstellation=constSym);

Generate signal data and apply 16-QAM modulation.

data = randi(s1,[0 M-1],numTones,1);
modOut = qammod(data,M,UnitAveragePower=true);

Apply OFDM modulation and pass the signal through the channel.

y = ofdmmod(modOut,nFFT,cpLen,nullIdx);
[fadSig,pg] = chan(y);

Determine symbol sampling offset.

symOffset = min(max(sampIdx),cpLen)
symOffset = 
9

OFDM demodulate the received signal with a time shift. Display the constellation diagram before equalization.

x = ofdmdemod(fadSig,nFFT,cpLen,symOffset,nullIdx);
cdScope(x);

Convert the vector of path gains, pg, to scalar tap gains that correspond to data subcarriers, h_datasubcarr. Use the h_datasubcarr tap gains for equalization during signal recovery.

hImp = complex(zeros(nFFT,1));
hImp(sampIdx) = mean(pg,1);
hall = fftshift(fft(hImp));
dataIdx = setdiff((1:nFFT)',nullIdx);
h_datasubcarr = hall(dataIdx);

Equalize the signal. Display the constellation diagram after equalization.

eqSig = x ./ h_datasubcarr;
cdScope(eqSig);

Demodulate the 16-QAM symbols to recover the signal. Compute the symbol error rate.

rxSym = qamdemod(eqSig,M,UnitAveragePower=true);
numErr = symerr(data,rxSym);
disp(['Number of symbol errors: ' num2str(numErr) ...
    ' out of ' num2str(length(data)) ' symbols.'])
Number of symbol errors: 2 out of 52 symbols.

OFDM-demodulate data input that includes null and pilot packing.

Initialize input parameters, defining locations for null and pilot subcarriers. Generate random data and perform OFDM modulation.

Mqam = 16;
Mpsk = 4;
nfft = 64;
cplen = 16;
nSym = 10;
nullIdx = [1:6 33 64-4:64]';
pilotIdx = [12 26 40 54]';
numDataCarrs = nfft-length(nullIdx)-length(pilotIdx);
dataSym = randi([0 Mqam-1],numDataCarrs,nSym);
qamSig = qammod(dataSym,Mqam,UnitAveragePower=true);
pilotSym = repmat((0:Mpsk-1).',1,nSym);
pilots = pskmod(pilotSym,Mpsk);
y2 = ofdmmod(qamSig,nfft,cplen,nullIdx,pilotIdx,pilots);

Demodulate the OFDM symbols. Compare the results to the original input data to show that the demodulated signal and the original data and pilot signals are equal.

symOffset = cplen;
[x2,rxPilots] = ofdmdemod(y2,nfft,cplen,symOffset,nullIdx,pilotIdx);
rxData = qamdemod(x2,Mqam,UnitAveragePower=true);
isequal(rxData,dataSym)
ans = logical
   1

rxPilotSym = pskdemod(rxPilots,Mpsk);
isequal(rxPilotSym,repmat((0:Mpsk-1).',1,nSym))
ans = logical
   1

Demodulate an oversampled OFDM modulation that has a sample offset. Insert nulls in the OFDM grid and oversample the output signal.

Initialize variables for the oversampling factor, FFT size, cyclic prefix length, and sample offset.

M = 64;
osf = 4/3;
nfft = 768;
cplen = 24;
sampOffset = 5;
symOffset = cplen - (sampOffset/osf);

Generate data symbols and OFDM-modulate the data.

dataSym = randi([0 M-1],nfft,1);
qamSig = qammod(dataSym,M,UnitAveragePower=true);
y3 = ofdmmod(qamSig,nfft,cplen,OversamplingFactor=osf);

Demodulate the signal and show the demodulated data symbols match the original input data symbols.

x3 = ofdmdemod(y3,nfft,cplen,symOffset,OversamplingFactor=osf);
rxSym = qamdemod(x3,M,UnitAveragePower=true);
isequal(rxSym,dataSym)
ans = logical
   1

Input Arguments

collapse all

OFDM-modulated baseband signal, specified as an (osf × NIn)-by-NStreams numeric array or a dlarray (Deep Learning Toolbox) object. For more information, see Array Support.

  • osf is the oversampling factor, as determined by OversamplingFactor.

  • When cplen is a scalar, NCP = cplen and NIn = NSym × (nfft + NCP).

  • When cplen is a row vector, NCPTotal = sum(cplen) and NIn = (NSym × nfft) + NCPTotal.

  • NSym is the number of symbols per transmit stream.

  • NStreams is the number of receive streams and must be less than or equal to the number of receive antennas.

Data Types: double | single
Complex Number Support: Yes

FFT length, specified as an integer greater than or equal to 8. nfft is the upper bound for the number of subcarriers (NDataSC) used in the demodulation process. NDataSC = nfft – length(nullidx) – length(pilotidx)

Data Types: double

Cyclic prefix length, specified as a scalar or row vector of length NSym. Cyclic prefix length must be nonnegative.

  • When you specify cplen as a scalar, the value must be in the range [0, nfft]. In this case, all symbols through all streams have the same cyclic prefix length.

  • When you specify cplen as a row vector of length NSym, the cyclic prefix length can vary across symbols but remains the same length through all streams.

NSym is the number of symbols per stream.

Data Types: double

Symbol sampling offset, specified as values from 0 to cplen.

  • If you do not specify symOffset, the default value is an offset equal to cplen.

  • If you specify symOffset as a scalar, the same offset is used for all symbols.

  • If you specify symOffset as a row vector, the offset value can be different for each symbol.

For information, see Windowing and Symbol Offset.

Data Types: double

Indices of null subcarrier locations, specified as a column vector with element values in the range [1, nfft]. For information, see Subcarrier Allocation and Guard Bands.

Data Types: double

Indices of pilot subcarrier locations, specified as a column vector with element values in the range [1, nfft]. For information, see Subcarrier Allocation and Guard Bands.

Data Types: double

Output Arguments

collapse all

Output baseband signal, returned as an NDataSC-by-NSym-by-NStreams numeric array or a dlarray (Deep Learning Toolbox). The output data format matches the input signal, X. For more information, see Array Support.

  • The number of data subcarriers, NDataSC = nfft – length(nullidx) – length(pilotidx).

  • NSym is the number of OFDM symbols per stream.

  • NStreams is the number of receive streams and is less than or equal to the number of receive antennas.

For information, see OFDM Demodulation.

Pilot subcarriers, returned as an NPilot-by-NSym-by-NStreams numeric array, dlarray (Deep Learning Toolbox), or gpuArray (Parallel Computing Toolbox). For more information, see Array Support. The output data format matches the input signal, X.

  • NPilot equals the length of pilotidx.

  • NSym is the number of OFDM symbols per stream.

  • NStreams is the number of receive streams and is less than or equal to the number of receive antennas.

Tip

The function assumes that the pilot subcarrier locations are the same across each OFDM symbol and transmit stream. To vary pilot subcarrier locations across OFDM symbols or streams, use the comm.OFDMDemodulator System object™.

More About

collapse all

Algorithms

collapse all

Extended Capabilities

expand all

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

Version History

Introduced in R2018a

expand all