Demodulate time-domain signal using orthogonal frequency division multiplexing (OFDM)
removes null subcarriers from the locations specified in
outSym = ofdmdemod(
nullidx. For this syntax, the symbol sampling offset is
applied to each OFDM symbol and the number of rows in the output is
length(, 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.
returns pilot subcarriers for the pilot indices specified in
pilots] = ofdmdemod(
pilotidx. For this syntax, the symbol sampling offset is
applied to each OFDM symbol and number of rows in the output is
length(, 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
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.
nfft = 64; cplen = [16 32]; nSym = 2; dataIn = complex(randn(nfft,nSym),randn(nfft,nSym)); y1 = ofdmmod(dataIn,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); max(x1-dataIn)
ans = 1×2 complex 10-15 × 0.2220 - 0.7772i 0.2498 - 0.8882i
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.
nfft = 64; cplen = 16; nSym = 10; nullIdx = [1:6 33 64-4:64]'; pilotIdx = [12 26 40 54]'; numDataCarrs = nfft-length(nullIdx)-length(pilotIdx); dataIn = complex(randn(numDataCarrs,nSym),randn(numDataCarrs,nSym)); pilots = repmat(pskmod((0:3).',4),1,nSym); y2 = ofdmmod(dataIn,nfft,cplen,nullIdx,pilotIdx,pilots);
Demodulate the OFDM symbols. Compare the results to the original input data to show that there is negligible difference between the demodulated signal and the original data and pilot signals.
symOffset = cplen; [x2,rxPilots] = ofdmdemod(y2,nfft,cplen,symOffset,nullIdx,pilotIdx); max(x2-dataIn)
ans = 1×10 complex 10-15 × 0.5551 + 0.2220i 0.2220 + 0.4441i 0.4441 - 0.2220i 0.4718 - 0.3331i -0.1665 - 0.4441i -0.3331 - 0.8049i 0.6661 - 0.2220i 0.0000 + 0.5829i 0.2220 + 0.4441i 0.3331 + 0.4441i
ans = 1×10 complex 10-15 × 0.0000 + 0.3331i 0.1837 - 0.2220i -0.4441 - 0.2776i 0.2220 + 0.2220i 0.2220 - 0.1665i 0.0000 - 0.3445i 0.3331 + 0.0441i -0.4441 - 0.1225i 0.4441 + 0.1943i 0.4441 + 0.3192i
ofdmSig— Modulated OFDM symbols
Modulated OFDM symbols, specified as a 2-D array of complex symbols.
Complex Number Support: Yes
nfft— FFT length
FFT length, specified as an integer greater than or equal to 8.
nfft is equivalent to the number of subcarriers
used in the demodulation process.
cplen— Cyclic prefix length
Cyclic prefix length, specified as a scalar or as a row vector of length NSym.
When you specify
cplen as a scalar, the
cyclic prefix length is the same for all symbols through all
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 antennas.
symOffset— Symbol sampling offset
cplen(default) | scalar | row vector
Symbol sampling offset, specified as values from 0 to
If you do not specify
default value is an offset equal to
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.
nullidx— Indices of null subcarrier locations
pilotidx— Indices of pilot subcarrier locations
outSym— Output demodulated symbols
pilots— Pilot subcarriers
Pilot subcarriers, returned as an
array of symbols. NPilot must
equal the length of
NSym is the number of OFDM
symbols per antenna. NR is the
number of receive antennas. The function assumes that the pilot subcarrier
locations are the same across each OFDM symbol and transmit antenna. Use the
comm.OFDMDemodulator to vary
pilot subcarrier locations across OFDM symbols or antennas.
An OFDM demodulator demultiplexes a multi-subcarrier time-domain signal using orthogonal frequency division modulation.
The OFDM demodulation uses an FFT operation that results in N parallel data streams. An OFDM demodulator consists of a bank of N correlators, with one correlator assigned to each OFDM subcarrier, followed by a parallel-to-serial conversion.
Individual OFDM subcarriers are allocated as data, pilot, or null subcarriers.
As shown here, subcarriers are designated as data, DC, pilot, or guard band subcarriers.
Data subcarriers transmit user data.
Pilot subcarriers are used for channel estimation.
Null subcarriers transmit no data. Subcarriers with no data are used to provide a DC null and serve as buffers between OFDM resource blocks.
The null DC subcarrier is the center of the frequency band with an index value of
nfft/2 + 1) if
nfft is even, or
nfft + 1) / 2) if
nfft is odd.
The guard bands provide buffers between consecutive OFDM symbols to protect the integrity of transmitted signals by reducing intersymbol interference.
Null subcarriers enable you to model guard bands and DC subcarrier locations for specific standards, such as the various 802.11 formats, LTE, WiMAX, or for custom allocations. You can allocate the location of nulls by assigning a vector of null subcarrier indices.
Similar to guard bands, guard intervals are used in OFDM to protect the integrity of transmitted signals by reducing intersymbol interference.
Assignment of guard intervals is analogous to the assignment of guard bands. You can model guard intervals to provide temporal separation between OFDM symbols. The guard intervals help preserve intersymbol orthogonality after the signal passes through time-dispersive channels. Guard intervals are created by using cyclic prefixes. Cyclic prefix insertion copies the last part of an OFDM symbol as the first part of the OFDM symbol.
As long as the span of the time dispersion does not exceed the duration of the cyclic prefix, the benefit of cyclic prefix insertion is maintained.
Inserting a cyclic prefix results in a fractional reduction of user data throughput because the cyclic prefix occupies bandwidth that could be used for data transmission.
To reduce intersymbol interference (ISI) introduced by signal windowing applied at the transmitter, the function applies a fractional symbol offset before demodulation of each OFDM symbol. Signal windowing is often applied to transmitted OFDM symbols to smooth the discontinuity between consecutive OFDM symbols. Windowing reduces intersymbol out-of-band emissions but increases ISI.
The windowed OFDM symbol consists of the cyclic prefix (CP), ODFM symbol data, plus windowing regions at the beginning and end of the symbol. The leading and trailing windowing shoulders have tails as shown in the figure.
To reduce ISI, you can align signal sample timing by specifying a symbol sampling offset that gets applied before OFDM symbol demodulation.
Specify the symbol sampling offset as a value from 0 to LCP.
When the symbol sampling offset is a scalar from 0 to LCP, the FFT window begins at the X+1 sample of the CP length.
When the symbol sampling offset is zero, no offset is applied and the FFT window starts at the first sample of the symbol.
When the symbol sampling offset is the cyclic prefix length, LCP, the FFT window begins after the last CP sample. This offset is the default setting if symbol sampling offset is not specified.