# Modeling a Communications System Using the Communications Toolbox

In this example, we use the Communications Toolbox to build a simple communications system. We'll start by formulating a random sequence of bits, encode those bits using a convolutional code, and then use a Gray-coded 16-QAM modulation scheme before pulse shaping using a raised cosine filter. Then we'll introduce noise using an AWGN channel. Next, we recover the signal and calculate the bit error rate.

At the end of this example, we provide a full list of links to the functions we use during this example.

## Contents

- Generating a Random Binary Message
- Encoding Bits with a Convolutional Code
- Generating a Bit-to-Symbol Mapping Using a Gray Code
- Modulating Using 16-QAM
- Pulse Shaping Signals Using an FIR RRC
- Adding AWG Noise to the Transmitted Signal
- Filtering Received Signals Using the RRC Filter
- Recovering the Signal
- Demodulating the Received Signal
- Recovering Bits from Symbols Using Gray Coding
- Decoding the Convolutional Code
- Calculating BERs with and Without Convolutional Code
- Functions Used in this Example
- Additional Information

## Generating a Random Binary Message

Our first task in this communication system is to generate a random binary message to transmit. We do this by using the `randint` function in the Communications Toolbox. The bits will be modulated using 16-QAM, so each symbol will be 4 bits long. We
use the following code to create the sequence and display the first 60 symbols:

M = 16; % Size of signal constellation k = log2(M); % Number of bits per symbol n = 1e4; % Number of total symbols to simulate % Create a binary signal as a column vector x = randint(n*k,1); % Random binary signal % Display the first 60 random bits stem(x(1:60),'filled'); title('Random Bits'); xlabel('Number of Bits'); ylabel('Binary Value'); set(gca,'yTick',[0 0.5 1],'XLim',[-2 62],'YLim',[-0.2 1.2],'Box','on'); set(gcf,'Color','w')

**Figure 1:** The first 60 random bits.

## Encoding Bits with a Convolutional Code

Now that we have created the random bits, our next step is to encode them. The Communications Toolbox includes a variety of coding schemes, including BCH codes, Reed-Solomon codes, cyclic codes, and convolutional codes. This example uses an industry-standard rate 1/2 convolutional coder. This diagram illustrates the matrix representation of our code:

**Figure 2:** The polynomial representation of our convolutional code.

The `convenc` function in the Communications Toolbox uses the trellis representation of a convolutional code to encode a sequence. We use
the `poly2trellis` function to convert from the polynomial representation of a code to the trellis representation. In the next code example,
we use these commands to encode the bit sequence convolutionally. Note that the codegen function is in octal format. See
the documentation on the `poly2trellis` function for more information.

% Declare variables codeRate = 1/2; % Code Rate constlen = 7; % Constraint Length codegen = [171 133]; % Generator Polynomials trellis = poly2trellis(constlen, codegen); % Create Trellis structure % Encode transmitted sequence xEnc = convenc(x, trellis);

## Generating a Bit-to-Symbol Mapping Using a Gray Code

After channel coding, we use a Gray code as the source code. Recall that one property of a Gray code is that any two adjacent
signals in a constellation have a Hamming distance of 1. The first step in Gray coding is generating a map that satisfies
the above condition. The `scatterplot` function in the Communications Toolbox shows the resulting constellation:

% Generate Gray code mapping % Start from a PSK constellation with sqrt(M) points grayPsk = bitxor(0:sqrt(M)-1,floor((0:sqrt(M)-1)/2))'; % Use it to create a QAM constellation with M points mapping = repmat(grayPsk,1,sqrt(M))+repmat(sqrt(M)*grayPsk',sqrt(M),1); mapping = mapping(:); % Display Bit-to-Symbol mapping t = qammod(mapping,M); scatterplot(t); set(get(gca,'Children'),'Marker','d','MarkerFaceColor','auto'); hold on; % Add labels showing the binary sequence at each constellation point for jj=1:length(t) text(real(t(jj))-0.5,imag(t(jj))+0.5,dec2base(jj-1,2,4)); end set(gca,'yTick',(-(k+1):2:k+1),'xTick',(-(k+1):2:k+1),... 'XLim',[-(k+1) k+1],'YLim',[-(k+1) k+1],'Box','on',... 'YGrid','on', 'XGrid','on'); xlabel ('In-Phase'); hold off; set(gcf,'Color','w')

**Figure 3:** A scatter plot of our Gray-coded QAM modulation.

We've generated the Gray code mapping. Next, we separate the sequence of bits into 4-bit symbols, convert each one to decimal format, and map it the appropriate Gray-coded sequence:

% Convert the sequence from a column vector to a 4-column matrix xSym = reshape(xEnc,k,n/codeRate).'; % Convert each row of the matrix from binary to decimal xSym = bi2de(xSym, 'left-msb'); % Permute the transmitted sequence using Gray code mapping xSym = mapping(xSym+1); % Display the first 35 transmitted symbols figure; stem(xSym(1:35)); title('Random Symbols'); xlabel('Number of Symbols'); ylabel('Integer Value {0..15}'); set(gca,'yTick',(0:M-1),'XLim',[-2 35+2],'YLim',[-0.2 M-1+.2],... 'Box','on','YGrid','on'); set(gcf,'Color','w')

**Figure 4:** The first 35 random symbols.

## Modulating Using 16-QAM

Now we have convolutionally coded the sequence of bits and mapped them to the decimal numbers 1-16 using a Gray code. Next,
we use the `qammod` function to convert the decimal numbers 1-16 to points in the two-dimensional space that is used to transmit the code. We'll
also display an eyediagram with the `eyediagram` function in the Communications Toolbox.

% Modulate the signal xMod = qammod(xSym,M); % Display eyediagram plot of modulated symbols eyediagram(xMod(1:100),2); subplot (2,1,2) xlabel ('Time'); set (gcf, 'Color', 'w')

**Figure 5:** Eyediagram of our QAM modulation.

## Pulse Shaping Signals Using an FIR RRC

We have modulated the sequence, and now we design an FIR root-raised cosine filter to reduce intersymbol interference (ISI).
This is a common filter in communications systems. We'll follow a two step process: first, we'll create the filter, and
then we'll use it to filter the signal. Let's use the Communications Toolbox function `rcosine` to create the filter.

% Define filter variables filtOrder = 40; overSamp = 4; delay = filtOrder/(overSamp*2); rollOff = .25; % Create filter rrcFilter = rcosine(1,overSamp,'fir/sqrt',rollOff,delay);

Next, let's use the Signal Processing Toolbox function `fvtool` to show the filter's impulse response. We can also use `fvtool` to show the magnitude response, phase response, group delay, and other characteristics of a filter.

% Display impulse response of Transmit filter hFV = fvtool(rrcFilter,1,'Analysis','Impulse'); xlabel ('Samples'); set (gcf, 'Color', 'w')

**Figure 6:** Impulse response of RRC filter.

After creating the root-raised cosine filter, our next step is to filter the incoming data stream. To further reduce the
risk of ISI, we upsample the sequence using the Signal Processing Toolbox function `upsample`. Then we filter it with the RRC using the MATLAB `filter` function. The resulting plots show the first 120 bits of the sequence before being filtered and after being filtered. The
real and imaginary parts are plotted separately.

% Upsample signal yModUp = upsample(xMod,overSamp); % Pad signal with zeros to flush filter yModUp = [yModUp; zeros(filtOrder,1)]; % Filter upsampled signal yTx = filter(rrcFilter,1,yModUp); % Plot the signal before and after filter figure; subplot(2,1,1); % Real part stem(real(yModUp(1:120))); hold on; plot(real(yTx(1+delay*overSamp:80+delay*overSamp)),'r-'); xlabel('Samples'); ylabel('Amplitude'); title ('Transmitted signal after Tx Filter - Real'); legend ('Digital signal before RRC', 'Analog signal after RRC') subplot(2,1,2); % Imaginary part stem(imag(yModUp(1:120))); hold on; plot(imag(yTx(1+delay*overSamp:80+delay*overSamp)),'r-'); xlabel('Samples'); ylabel('Amplitude'); title ('Transmitted signal after Tx Filter - Imag'); legend ('Digital signal before RRC', 'Analog signal after RRC') hold off; set (gcf, 'Color', 'w')

**Figure 7:** Comparison of signal before and after RRC.

## Adding AWG Noise to the Transmitted Signal

We have encoded and filtered the signal, and it is ready to be transmitted. The Communications Toolbox includes several kinds
of channels, including Rician channels, Rayleigh channels, and AWGN channels. In this example, we use an AWGN channel to
add white Gaussian noise to the signal. We'll also use the `scatterplot` function to plot the received and transmitted signals for comparison:

% SNR per coded bit EbNo = 10; % SNR per uncoded bit EsNo = EbNo+10*log10(k)-10*log10(overSamp)-10*log10(1/codeRate); % Add the noise yNoisy = awgn(yTx,EsNo,'measured'); % Plot received signal vs. transmitted signal h=scatterplot(yNoisy(1:overSamp:end).*sqrt(overSamp),1,0,'b.'); hold on; scatterplot(xMod,1,0,'rx',h); set(get(get(h,'children'),'children'),'MarkerSize',10,'LineWidth',4); title('Received vs. Transmitted Signal (Downsampled for visualization)'); axis([-(k+1) k+1 -(k+1) k+1]); xlabel ('In-Phase'); hold off; set (gcf, 'Color', 'w')

**Figure 8:** Symbols before and after noise.

## Filtering Received Signals Using the RRC Filter

The signal has now been transmitted over the channel and it needs to be recovered. The steps to recover the original signal are as follows:

- Recover the signal from the RRC.
- Demodulate the signal.
- Undo the Gray code.
- Decode the convolutional code.

## Step 1: Recovering the Signal

The first step is to recover the signal from the RRC. One of the advantages of an RRC is that we can use the same filter to recover the signal that we used to encode it. After decoding, we downsample the signal, because it was upsampled before it was filtered. After the data is filtered and downsampled, we plot the transmitted signal and the received signals:

% Filter received signal using Tx filter yRx = filter(rrcFilter,1,yNoisy); % Downsample received signal yRxDown = downsample(yRx,overSamp); % Compensate for filter delay yRxDown = yRxDown(filtOrder/overSamp+1:end); % Plot the received signal, the received analog signal after the RRC, and % the resulting digital signal figure; subplot(2,1,1); plot(real(yNoisy(delay*overSamp+1:delay*overSamp+80)),'ko-'); hold on; plot(real(yRx(2*delay*overSamp+1:2*delay*overSamp+80)),'bx-'); stem(upsample(real(yRxDown(1:80/overSamp)),overSamp),'r-'); grid on; axis([0 80 -4 4]); legend('Received signal','Received filtered signal','Rx sampling point'); % For comparison, replot the transmitted signal subplot(2,1,2); plot(real(yTx(1+delay*overSamp:80+delay*overSamp)),'rd-.'); hold on; stem(real(yModUp(1:80)),'b'); xlabel('Samples'); ylabel('Amplitude'); legend('Transmitted filtered signal','Original Tx signal'); axis([0 80 -4 4]); grid on; set(gcf,'Color','w')

**Figure 9:** Comparison of signal before and after RRC.

## Step 2: Demodulating the Received Signal

After filtering the signal with the RRC, we'll demodulate the signal using the `qamdemod` function in the Communications Toolbox.

ySym = qamdemod(yRxDown,M);

## Step 3: Recovering Bits from Symbols Using Gray Coding

Next, let's demap the received data using the Gray mapping. Then we can compare the sequence to the original sequence after
it was encoded with the convolutional encoder. We use the `biterr` function to do this comparison:

[dummy demapping] = sort(mapping); demapping = demapping - 1; ySym = demapping(ySym+1); % Convert integers to bits yBits = de2bi(ySym,'left-msb'); yBits = reshape(yBits.',numel(yBits),1);

## Step 4: Decoding the Convolutional Code

The last step in the system is to decode the code using a Viterbi decoder. To do this, we use the `vitdec` function in the Communications Toolbox. The `vitdec` function uses the same trellis for encoding and decoding the sequence. This function can specify both the initial state
of a trellis and its final state. It can also decode using hard-decision or soft-decision decoding. Our example uses hard-decision
decoding:

% Define variables tblen = 32; % Traceback length % Decode received signal assuming an all-zero initial state y = vitdec(yBits, trellis, tblen, 'cont','hard');

## Calculating BERs with and Without Convolutional Code

In this section, we calculate two BERs for the sequence: one for when the convolutional code is used and one for when it is
not. We'll use the `biterr` function in the Communications Toolbox for the calculations. Finally, we use the `berawgn` function to calculate the theoretical error for a non-coded AWGN channel with the specified parameters:

% Compute BER without convolutional coding [numErrors_Sym_no_code, bitError_Sym_no_code] = biterr(xEnc,yBits) % Compute BER with convolutional coding [numErrors_with_code,bitError_with_code] = biterr(x(1:end-tblen),y(tblen+1:end)) % Compute theoretical BER for an AWGN channel with parameters of this % channel ber_theory = berawgn (EsNo, 'qam', M)

numErrors_Sym_no_code = 1374 bitError_Sym_no_code = 0.0172 numErrors_with_code = 0 bitError_with_code = 0 ber_theory = 0.0168

## Functions Used in this Example

For more information about any of the functions used in this example, click on the following links. All functions are in the Communications Toolbox unless otherwise noted.

`randint`- Creates a sequence of random bits.`poly2trellis`- Converts a convolutional code generator polynomial to a trellis.`convenc`- Encodes a sequence of bits using a convolutional code with a given trellis.`scatterplot`- Generates a scatter plot to show a signal constellation.`qammod`- Modulates a sequence using QAM.`eyediagram`- Displays an eyediagram of a modulated sequence.`rcosine`- Designs a raised cosine filter.`fvtool`- Graphically shows a filter's impulse response, magnitude response, and several other representations. (Signal Processing Toolbox)`upsample`- Upsamples a sequence by inserting zeros. (Signal Processing Toolbox)`filter`- Filters a sequence using a given FIR or IIR filter. (Included in MATLAB)`awgn`- Transmits data over an AWGN channel.- See this overview of channel features in the toolbox.
`downsample`- Downsamples a sequence. (Signal Processing Toolbox)`qamdemod`- Demodulates a sequence that was modulated using QAM.`vitdec`- Decodes a sequence using a Viterbi decoder.`biterr`- Calculates the bit error rate of a sequence.`berawgn`- Calculates the uncoded theoretical bit error rate over an AWGN channel without coding.

## Additional Information

For more information on using the Communications Toolbox, see:

Additional Communications Toolbox Examples

Communications Toolbox Documentation

From the main Communications Toolbox page you can download a free 30-day trial, read the documentation and user stories, request more information, and get pricing information.