Use Pulse Shaping on 16-QAM Signal
This example extends the Examine 16-QAM Using MATLAB example to perform pulse shaping and raised cosine filtering by using a pair of square-root raised cosine (RRC) filters. The rcosdesign
function creates the filters. BER performance can be improved by adding forward error correction (FEC) to the communication link. To add FEC to the communications link with pulse shape filtering example, see the Use Forward Error Correction on 16-QAM Signal example.
This example shows how to process a binary data stream by using a communications link that consists of a baseband modulator, channel, demodulator, and pulse shaping and raised cosine filtering. The example computes the bit error rate (BER), displays filter effects in eye diagrams, and displays the transmitted and received signals in a constellation diagram.
Establish Simulation Framework
Define simulation parameters for a 16-QAM modulation scheme with raised cosine filtering, and an AWGN channel.
M = 16; % Modulation order k = log2(M); % Bits per symbol numBits = k*7.5e4; % Bits to process sps = 4; % Samples per symbol (oversampling factor)
Create RRC Filter
Set the RRC filter parameters.
filtlen = 10; % Filter length in symbols rolloff = 0.25; % Filter rolloff factor
Use the rcosdesign
function to create an RRC filter.
rrcFilter = rcosdesign(rolloff,filtlen,sps);
Use impz
to display the RRC filter impulse response.
impz(rrcFilter)
Compute System BER
Use the randi
function to generate random binary data. Set the rng
function to its default state, or any static seed value, so that the example produces repeatable results.
rng default; % Default random number generator dataIn = randi([0 1],numBits,1); % Generate vector of binary data
Use the bit2int
function to convert k
-tuple binary words into integer symbols.
dataSymbolsIn = bit2int(dataIn,k);
Apply 16-QAM modulation using the qammod
function.
dataMod = qammod(dataSymbolsIn,M);
Use the upfirdn
function to upsample the signal by the oversampling factor and apply the RRC filter. The upfirdn
function pads the upsampled signal with zeros at the end to flush the filter. Then, the function applies the filter.
txFiltSignal = upfirdn(dataMod,rrcFilter,sps,1);
Use the number of bits per symbol (k
), the number of samples per symbol (sps
), and the convertSNR
function to convert the ratio of energy per bit to noise power spectral density (EbNo
) to an SNR value for use by the awgn
function.
EbNo = 10; snr = convertSNR(EbNo,'ebno', ... samplespersymbol=sps, ... bitspersymbol=k);
Pass the filtered signal through an AWGN channel.
rxSignal = awgn(txFiltSignal,snr,'measured');
Use the upfirdn
function on the received signal to downsample and filter the signal. Downsample by using the same oversampling factor applied for upsampling the transmitted signal. Filter by using the same RRC filter applied to the transmitted signal.
Each filtering operation delays the signal by half of the filter length in symbols, filtlen
/2. So, the total delay from transmit and receive filtering equals the filter length, filtlen
. For the BER computation, the transmitted and received signals must be the same size and you must account for the delay between the transmitted and received signal. Remove the first filtlen
symbols in the decimated signal to account for the cumulative delay of the transmit and receive filtering operations. Remove the last filtlen
symbols in the decimated signal to ensure the number of samples in the demodulator output matches the number of samples in the modulator input.
rxFiltSignal = ... upfirdn(rxSignal,rrcFilter,1,sps); % Downsample and filter rxFiltSignal = ... rxFiltSignal(filtlen + 1:end - filtlen); % Account for delay
Use the qamdemod
function to demodulate the received filtered signal.
dataSymbolsOut = qamdemod(rxFiltSignal,M);
Convert the recovered integer symbols into binary data by using the int2bit
function.
dataOut = int2bit(dataSymbolsOut,k);
Determine the number of errors and the associated BER by using the biterr
function.
[numErrors,ber] = biterr(dataIn,dataOut); fprintf(['\nFor an EbNo setting of %3.1f dB, ' ... 'the bit error rate is %5.2e, based on %d errors.\n'], ... EbNo,ber,numErrors)
For an EbNo setting of 10.0 dB, the bit error rate is 1.92e-03, based on 575 errors.
Visualize Filter Effects
To visualize the filter effects in an eye diagram, reduce the setting and regenerate the received data. Visualizing a high SNR signal with no other multipath effects, you can use eye diagrams to highlight the intersymbol interference (ISI) reduction at the output for the pair of pulse shaping RRC filters. The RRC filter does not have zero-ISI until it is paired with the second RRC filter to form in cascade a raised cosine filter.
EbNo = 20; snr = convertSNR(EbNo,'ebno', ... samplespersymbol=sps, ... bitspersymbol=k); rxSignal = awgn(txFiltSignal,snr,'measured'); rxFiltSignal = ... upfirdn(rxSignal,rrcFilter,1,sps); % Downsample and filter rxFiltSignal = ... rxFiltSignal(filtlen + 1:end - filtlen); % Account for delay
Create an eye diagram for a portion of the filtered noiseless signal to visualize the effect of the pulse shaping. The transmitted signal has RRC filtering and shows ISI as a narrowing of the eye-opening.
eyediagram(txFiltSignal(1:2000),sps*2);
Displaying the eye diagram of the signal after the channel noise shows the signal with RRC filtering and noise. The noise level causes further narrowing of the eye diagram eye-opening.
eyediagram(rxSignal(1:2000),sps*2);
Displaying the eye diagram of the signal after the receive filtering is applied shows the signal with raised cosine filtering. The wider eye diagram eye-openings, the signal has less ISI with raised cosine filtering as compared to the signal with RRC filtering.
eyediagram(rxFiltSignal(1:2000),2);
Create a constellation diagram of the received signal before and after filtering. Scale the received signal by the square root of the number of samples per symbol to normalize the transmit and receive power levels.
scatplot = scatterplot(sqrt(sps)*... rxSignal(1:sps*5e3),... sps,0); hold on; scatterplot(rxFiltSignal(1:5e3),1,0,'bx',scatplot); title('Received Signal, Before and After Filtering'); legend('Before Filtering','After Filtering'); axis([-5 5 -5 5]); % Set axis ranges hold off;