Note: This page has been translated by MathWorks. Click here to see

To view all translated materials including this page, select Country from the country navigator on the bottom of this page.

To view all translated materials including this page, select Country from the country navigator on the bottom of this page.

This section builds an example step-by-step to give you a first
look at the Communications Toolbox™ software. This section also
shows how Communications Toolbox functionalities build upon the
computational and visualization tools in the underlying MATLAB^{®} environment.

This example shows how to process a binary data stream using a communication system that consists of a baseband modulator, channel, and demodulator. The system's bit error rate (BER) is computed and the transmitted and received signals are displayed in a constellation diagram.

The following table summarizes the basic operations used, along with relevant Communications Toolbox and MATLAB functions. The example uses baseband 16-QAM (quadrature amplitude modulation) as the modulation scheme and AWGN (additive white Gaussian noise) as the channel model.

Task | Function |
---|---|

Generate a Random Binary Data Stream | `randi` |

Convert the Binary Signal to an Integer-Valued Signal | `bi2de` |

Modulate using 16-QAM | `qammod` |

Add White Gaussian Noise | `awgn` |

Create a Constellation Diagram | `scatterplot` |

Demodulate using 16-QAM | `qamdemod` |

Convert the Integer-Valued Signal to a Binary Signal | `de2bi` |

Compute the System BER | `biterr` |

The conventional format for representing a signal in MATLAB is
a vector or matrix. This example uses the `randi`

function
to create a column vector that contains the values of a binary data
stream. The length of the binary data stream (that is, the number
of rows in the column vector) is arbitrarily set to 30,000.

The code below also creates a stem plot of a portion of the
data stream, showing the binary values. Notice the use of the colon
(`:`

) operator in MATLAB to select a portion
of the vector.

Define parameters.

M = 16; % Size of signal constellation k = log2(M); % Number of bits per symbol n = 30000; % Number of bits to process numSamplesPerSymbol = 1; % Oversampling factor

Create a binary data stream as a column vector.

rng default % Use default random number generator dataIn = randi([0 1],n,1); % Generate vector of binary data

Plot the first 40 bits in a stem plot.

stem(dataIn(1:40),'filled'); title('Random Bits'); xlabel('Bit Index'); ylabel('Binary Value');

The `qammod`

function implements a rectangular,
M-ary QAM modulator, M being 16 in this example. The default configuration
is such that the object receives integers between 0 and 15 rather
than 4-tuples of bits. In this example, we preprocess the binary data
stream `dataIn`

before using the `qammod`

function.
In particular, the `bi2de`

function is used to convert
each 4-tuple to a corresponding integer.

Perform a bit-to-symbol mapping.

dataInMatrix = reshape(dataIn,length(dataIn)/k,k); % Reshape data into binary k-tuples, k = log2(M) dataSymbolsIn = bi2de(dataInMatrix); % Convert to integers

Plot the first 10 symbols in a stem plot.

figure; % Create new figure window. stem(dataSymbolsIn(1:10)); title('Random Symbols'); xlabel('Symbol Index'); ylabel('Integer Value');

Having generated the `dataSymbolsIn`

column
vector, use the `qammod`

function to apply 16-QAM
modulation for both binary and Gray coded bit-to-symbol mappings.
Recall that `M`

is 16, the alphabet size.

Apply modulation.

dataMod = qammod(dataSymbolsIn,M,'bin'); % Binary coding, phase offset = 0 dataModG = qammod(dataSymbolsIn,M); % Gray coding, phase offset = 0

The results are complex column vectors whose values are elements of the 16-QAM signal constellation. A later step in this example will plot the constellation diagram.

To learn more about modulation functions, see Digital Modulation. Also,
note that the `qammod`

function does not apply pulse
shaping. To extend this example to use pulse shaping, see Pulse Shaping Using a Raised Cosine Filter.
For an example that uses Gray coding with PSK modulation, see Gray Coded 8-PSK.

The ratio of bit energy to noise power spectral density, *E _{b}/N_{0}*,
is arbitrarily set to 10 dB. From that value, the signal-to-noise
ratio (SNR) can be determined. Given the SNR, the modulated signal,

`dataMod`

,
is passed through the channel by using the `awgn`

function.The `numSamplesPerSymbol`

variable is not significant
in this example but will make it easier to extend the example later
to use pulse shaping.

Calculate the SNR when the channel has an *E _{b}/N_{0}* =
10 dB.

EbNo = 10; snr = EbNo + 10*log10(k) - 10*log10(numSamplesPerSymbol);

Pass the signal through the AWGN channel for both the binary and Gray coded symbol mappings.

receivedSignal = awgn(dataMod,snr,'measured'); receivedSignalG = awgn(dataModG,snr,'measured');

The `scatterplot`

function is used to display
the in-phase and quadrature components of the modulated signal, `dataMod`

,
and its received, noisy version, `receivedSignal`

.
By looking at the resultant diagram, the effects of AWGN are readily
observable.

Use the `scatterplot`

function to show the
constellation diagram.

sPlotFig = scatterplot(receivedSignal,1,0,'g.'); hold on scatterplot(dataMod,1,0,'k*',sPlotFig)

The `qamdemod`

function is used to demodulate
the received data and output integer-valued data symbols.

Demodulate the received signals using the `qamdemod`

function.

```
dataSymbolsOut = qamdemod(receivedSignal,M,'bin');
dataSymbolsOutG = qamdemod(receivedSignalG,M);
```

The `de2bi`

function is used to convert the
data symbols from the QAM demodulator, `dataSymbolsOut`

,
into a binary matrix, `dataOutMatrix`

with dimensions
of N_{sym}-by-N_{bits/sym},
where N_{sym} is the total number of QAM symbols
and N_{bits/sym} is the number of bits per symbol,
four in this case. The matrix is then converted into a column vector
whose length is equal to the number of input bits, 30,000. The process
is repeated for the Gray coded data symbols, `dataSymbolsOutG`

.

Reverse the bit-to-symbol mapping performed earlier.

dataOutMatrix = de2bi(dataSymbolsOut,k); dataOut = dataOutMatrix(:); % Return data in column vector dataOutMatrixG = de2bi(dataSymbolsOutG,k); dataOutG = dataOutMatrixG(:); % Return data in column vector

The function `biterr`

is used to calculate
the bit error statistics from the original binary data stream, `dataIn`

,
and the received data streams, `dataOut`

and `dataOutG`

.

Use the error rate function to compute the error statistics
and use `fprintf`

to display the results.

[numErrors,ber] = biterr(dataIn,dataOut); fprintf('\nThe binary coding bit error rate = %5.2e, based on %d errors\n', ... ber,numErrors)

The binary coding bit error rate = 2.40e-03, based on 72 errors

[numErrorsG,berG] = biterr(dataIn,dataOutG); fprintf('\nThe Gray coding bit error rate = %5.2e, based on %d errors\n', ... berG,numErrorsG)

The Gray coding bit error rate = 1.33e-03, based on 40 errors

Observe that Gray coding significantly reduces the bit error rate.

The example in the previous section, Modulate a Random Signal, created a scatter plot from the modulated signal. Although the plot showed the points in the QAM constellation, the plot did not indicate which integers of the modulator are mapped to a given constellation point. This section illustrates two possible mappings: 1) binary coding, and 2) Gray coding. It was previously demonstrated that Gray coding provides superior bit error rate performance.

Apply 16-QAM modulation to all possible input values using the default symbol mapping, binary.

M = 16; % Modulation order x = (0:15)'; % Integer input y1 = qammod(x,16,'bin'); % 16-QAM output

Use the `scatterplot`

function to plot the
constellation diagram and annotate it with binary representations
of the constellation points.

```
scatterplot(y1)
text(real(y1)+0.1, imag(y1), dec2bin(x))
title('16-QAM, Binary Symbol Mapping')
axis([-4 4 -4 4])
```

Apply 16-QAM modulation to all possible input values using Gray-coded symbol mapping.

y2 = qammod(x,16,'gray'); % 16-QAM output, Gray-coded

Use the `scatterplot`

function to plot the
constellation diagram and annotate it with binary representations
of the constellation points.

```
scatterplot(y2)
text(real(y2)+0.1, imag(y2), dec2bin(x))
title('16-QAM, Gray-coded Symbol Mapping')
axis([-4 4 -4 4])
```

In the binary mapping plot, notice that symbols 1 (```
0
0 0 1
```

) and 2 (`0 0 1 0`

) correspond to
adjacent constellation points on the left side of the diagram. The
binary representations of these integers differ by two bits unlike
the Gray-coded signal constellation in which each point differs by
only one bit from its direct neighbors, which leads to better BER
performance.

The Modulate a Random Signal example was modified to employ
a pair of square-root raised cosine (RRC) filters to perform pulse
shaping and matched filtering. The filters are created by the `rcosdesign`

function.
In Error Correction using a Convolutional Code, this example is extended by introducing
forward error correction (FEC) to improve BER performance.

To create a BER simulation, a modulator, demodulator, communication channel, and error counter functions must be used and certain key parameters must be specified. In this case, 16-QAM modulation is used in an AWGN channel.

Set the simulation parameters.

M = 16; % Size of signal constellation k = log2(M); % Number of bits per symbol numBits = 3e5; % Number of bits to process numSamplesPerSymbol = 4; % Oversampling factor

Set the square-root, raised cosine filter parameters.

span = 10; % Filter span in symbols rolloff = 0.25; % Roloff factor of filter

Create a square-root, raised cosine filter using the `rcosdesign`

function.

rrcFilter = rcosdesign(rolloff, span, numSamplesPerSymbol);

Display the RRC filter impulse response using the `fvtool`

function.

fvtool(rrcFilter,'Analysis','Impulse')

Use the `randi`

function to generate random
binary data. The `rng`

function should be set to
its default state so that the example produces repeatable results.

rng default % Use default random number generator dataIn = randi([0 1], numBits, 1); % Generate vector of binary data

Reshape the input vector into a matrix of 4-bit binary data, which is then converted into integer symbols.

dataInMatrix = reshape(dataIn, length(dataIn)/k, k); % Reshape data into binary 4-tuples dataSymbolsIn = bi2de(dataInMatrix); % Convert to integers

Apply 16-QAM modulation using `qammod`

.

dataMod = qammod(dataSymbolsIn, M);

Using the `upfirdn`

function, upsample and
apply the square-root, raised cosine filter.

txSignal = upfirdn(dataMod, rrcFilter, numSamplesPerSymbol, 1);

The `upfirdn`

function upsamples the modulated
signal, `dataMod`

, by a factor of `numSamplesPerSymbol`

,
pads the upsampled signal with zeros at the end to flush the filter
and then applies the filter.

Set the *E _{b}/N_{0}* to
10 dB and convert the SNR given the number of bits per symbol,

EbNo = 10; snr = EbNo + 10*log10(k) - 10*log10(numSamplesPerSymbol);

Pass the filtered signal through an AWGN channel.

`rxSignal = awgn(txSignal, snr, 'measured');`

Filter the received signal using the square-root, raised cosine filter and remove a portion of the signal to account for the filter delay in order to make a meaningful BER comparison.

rxFiltSignal = upfirdn(rxSignal,rrcFilter,1,numSamplesPerSymbol); % Downsample and filter rxFiltSignal = rxFiltSignal(span+1:end-span); % Account for delay

These functions apply the same square-root raised cosine filter
that the transmitter used earlier, and then downsample the result
by a factor of `nSamplesPerSymbol`

. The last command
removes the first `Span`

symbols and the last `Span`

symbols
in the decimated signal because they represent the cumulative delay
of the two filtering operations. Now `rxFiltSignal`

,
which is the input to the demodulator, and `dataSymbolsOut`

,
which is the output from the modulator, have the same vector size.
In the part of the example that computes the bit error rate, it is
required to compare vectors that have the same size.

Apply 16-QAM demodulation to the received, filtered signal.

dataSymbolsOut = qamdemod(rxFiltSignal, M);

Using the `de2bi`

function, convert the incoming
integer symbols into binary data.

```
dataOutMatrix = de2bi(dataSymbolsOut,k);
dataOut = dataOutMatrix(:); % Return data in column vector
```

Apply the `biterr`

function to determine
the number of errors and the associated BER.

[numErrors, ber] = biterr(dataIn, dataOut); fprintf('\nThe bit error rate = %5.2e, based on %d errors\n', ... ber, numErrors)

The bit error rate = 1.83e-03, based on 550 errors

Create an eye diagram for a portion of the filtered signal.

eyediagram(txSignal(1:2000),numSamplesPerSymbol*2);

The `eyediagram`

function creates an eye
diagram for part of the filtered noiseless signal. This diagram illustrates
the effect of the pulse shaping. Note that the signal shows significant
intersymbol interference (ISI) because the filter is a square-root
raised cosine filter, not a full raised cosine filter.

Created a scatter plot of the received signal before and after filtering.

Notice that the first `scatterplot`

command
scales `rxSignal`

by `sqrt(numSamplesPerSymbol)`

when
plotting. This is because the filtering operation changes the signal's
power.

Building upon the Pulse Shaping Using a Raised Cosine Filter example, this example shows how bit error rate performance improves with the addition of forward error correction, FEC, coding.

To create the simulation, a modulator, demodulator, raised cosine filter pair, communication channel, and error counter functions are used and certain key parameters are specified. In this case, a 16-QAM modulation scheme with raised cosine filtering is used in an AWGN channel. With the exception of the number of bits, the specified parameters are identical to those used in the previous example.

Set the simulation variables. The number of bits is increased from the previous example so that the bit error rate may be estimated more accurately.

M = 16; % Size of signal constellation k = log2(M); % Number of bits per symbol numBits = 100000; % Number of bits to process numSamplesPerSymbol = 4; % Oversampling factor

Use the `randi`

function to generate random,
binary data once the `rng`

function has been called.
When set to its default value, the `rng`

function
ensures that the results from this example are repeatable.

rng default % Use default random number generator dataIn = randi([0 1], numBits, 1); % Generate vector of binary data

The performance of the Pulse Shaping Using a Raised Cosine Filter example can be significantly improved upon by employing forward error correction. In this example, convolutional coding is applied to the transmitted bit stream in order to correct errors arising from the noisy channel. Because it is often implemented in real systems, the Viterbi algorithm is used to decode the received data. A hard decision algorithm is used, which means that the decoder interprets each input as either a “0” or a “1”.

Define a convolutional coding trellis for a rate 2/3 code. The `poly2trellis`

function
defines the trellis that represents the convolutional code that `convenc`

uses
for encoding the binary vector, `dataIn`

. The two
input arguments of the `poly2trellis`

function
indicate the code’s constraint length and generator polynomials,
respectively.

tPoly = poly2trellis([5 4],[23 35 0; 0 5 13]); codeRate = 2/3;

Encode the input data using the previously created trellis.

dataEnc = convenc(dataIn, tPoly);

The encoded binary data is converted into an integer format so that 16-QAM modulation can be applied.

Reshape the input vector into a matrix of 4-bit binary data, which is then converted into integer symbols.

dataEncMatrix = reshape(dataEnc, ... length(dataEnc)/k, k); % Reshape data into binary 4-tuples dataSymbolsIn = bi2de(dataEncMatrix); % Convert to integers

Apply 16-QAM modulation.

dataMod = qammod(dataSymbolsIn, M);

As in the Pulse Shaping Using a Raised Cosine Filter example, RRC filtering
is applied to the modulated signal before transmission. The example
makes use of the `rcosdesign`

function to create
the filter and the `upfirdn`

function to filter
the data.

Specify the filter span and rolloff factor for the square-root, raised cosine filter.

span = 10; % Filter span in symbols rolloff = 0.25; % Roloff factor of filter

Create the filter using the `rcosdesign`

function.

rrcFilter = rcosdesign(rolloff, span, numSamplesPerSymbol);

Using the `upfirdn`

function, upsample and
apply the square-root, raised cosine filter.

txSignal = upfirdn(dataMod, rrcFilter, numSamplesPerSymbol, 1);

Calculate the signal-to-noise ratio, SNR, based on the input *E _{b}/N_{0}*,
the number of samples per symbol, and the code rate. Converting from

`codeRate`

information
bits. More concretely, three symbols correspond to 12 coded bits in
16-QAM, which correspond to 8 uncoded (information) bits.EbNo = 10; snr = EbNo + 10*log10(k*codeRate)-10*log10(numSamplesPerSymbol);

Pass the filtered signal through an AWGN channel.

`rxSignal = awgn(txSignal, snr, 'measured');`

Filter the received signal using the RRC filter and remove a portion of the signal to account for the filter delay in order to make a meaningful BER comparison.

rxFiltSignal = upfirdn(rxSignal,rrcFilter,1,numSamplesPerSymbol); % Downsample and filter rxFiltSignal = rxFiltSignal(span+1:end-span); % Account for delay

Demodulate the received, filtered signal using the `qamdemod`

function.

dataSymbolsOut = qamdemod(rxFiltSignal, M);

Use the `de2bi`

function to convert the incoming
integer symbols into bits.

```
dataOutMatrix = de2bi(dataSymbolsOut,k);
codedDataOut = dataOutMatrix(:); % Return data in column vector
```

Decode the convolutionally encoded data with a Viterbi decoder.
The syntax for the `vitdec`

function instructs
it to use hard decisions. The 'cont' argument instructs it to use
a mode designed for maintaining continuity when the function is repeatedly
invoked (as in a loop). Although this example does not use a loop,
the 'cont' mode is used for the purpose of illustrating how to compensate
for the delay in this decoding operation.

traceBack = 16; % Traceback length for decoding numCodeWords = floor(length(codedDataOut)*2/3); % Number of complete codewords dataOut = vitdec(codedDataOut(1:numCodeWords*3/2), ... % Decode data tPoly,traceBack,'cont','hard');

Using the `biterr`

function, compare `dataIn`

and `dataOut`

to
obtain the number of errors and the bit error rate while taking the
decoding delay into account. The continuous operation mode of the
Viterbi decoder incurs a delay whose duration in bits equals the traceback
length, `traceBack`

, times the number of input streams
at the encoder. For this rate 2/3 code, the encoder has two input
streams, so the delay is 2×`traceBack`

bits.
As a result, the first 2×`traceBack`

bits in
the decoded vector, `dataOut`

, are zeros. When computing
the bit error rate, the first 2×`traceBack`

bits
in `dataOut`

and the last 2×`traceBack`

bits
in the original vector, `dataIn`

, are discarded.
Without delay compensation, the BER computation is meaningless.

decDelay = 2*traceBack; % Decoder delay, in bits [numErrors, ber] = ... biterr(dataIn(1:end-decDelay),dataOut(decDelay+1:end)); fprintf('\nThe bit error rate = %5.2e, based on %d errors\n', ... ber, numErrors)

The bit error rate = 6.00e-05, based on 6 errors

It can be seen that for the same E_{b}/N_{0} of
10 dB, the number of errors when using FEC is reduced as the BER is
improves from 2.0×10^{-3} to 6.9×10^{-4}.

The decoding operation in this example incurs a delay, which means that the output of the decoder lags the input. Timing information does not appear explicitly in the example, and the duration of the delay depends on the specific operations being performed. Delays occur in various communications-related operations, including convolutional decoding, convolutional interleaving/deinterleaving, equalization, and filtering. To find out the duration of the delay caused by specific functions or operations, refer to the specific documentation for those functions or operations. For example:

The

`vitdec`

reference page