QPSK Receiver Using Software-Defined Radio
R2026bThis example shows how to implement a QPSK receiver using a Universal Software Radio Peripheral (USRP™) or ADALM-PLUTO radio. The receiver addresses practical issues in wireless communications, such as carrier frequency and phase offset, timing offset, and frame synchronization.
The system receives the signal sent by the QPSK transmitter, demodulates the received symbols and prints a simple message to the MATLAB® command line. If the selected radio is ADALM-Pluto, the data rate is 1 Mbps and if the selected radio is USRP, the data rate is 8Mbps. The USRP radio uses background processing to achieve higher samples like 8Msps.
For more information on designing a QPSK transmitter, see the QPSK Transmitter Using Software-Defined Radio example.
This example shows how to:
Use the Communications Toolbox™ System objects for QPSK system design, including coarse and fine carrier frequency compensation, timing recovery, frame synchronization, carrier phase ambiguity resolution, and message decoding.
Implement a real QPSK-based transmission-reception environment in MATLAB using software-defined radio (SDR) System objects.
Required Hardware and Software
To run this example, you need one of these USRP or ADALM-PLUTO radios and the corresponding hardware support package.
USRP™ N2xx series or B2xx series radio and Communications Toolbox Support Package for USRP Radio. For more information, see USRP Radio and Supported Hardware and Required Software.
USRP™ E320, N3xx, X3xx, or X4xx series radio and Wireless Testbench Support Package for NI USRP Radios. For more information, see Supported Radio Devices (Wireless Testbench).
ADALM-PLUTO radio and Communications Toolbox Support Package for Analog Devices® ADALM-PLUTO Radio. For more information, see ADALM-Pluto Radio.
Initialization

Select Radio
Select the required radio SDRName from the availableRadios table. For more information about discovering radios, see findsdr.
SDRName ="B210"; Address =
"30F597A"; if strcmpi(SDRName,"Pluto") SDRType = "Pluto"; else SDRType = "USRP"; end radioStatus = findsdr(SDRType=SDRType, Address=Address, StatusType="RxAvailable");
Checking radio connections ...
Initialize Receiver Parameters
The sdrQPSKReceiverInit.m script initializes the simulation parameters and generates the structure prmQPSKReceiver.
if strcmpi(SDRName,'Pluto') sampleRate =1000000; else sampleRate =
8000000; end CFCAlgorithm =
"FFT-Based"; % Select the algorithm to compensate coarse frequency offset
Different radios and RF cards support different center frequency ranges. For successful reception, set the receiver System object™'s center frequency to a value that is supported by the selected RF card and matches the transmitted signal frequency.
SDRGain =50; SDRCenterFrequency =
915000000; SDRStopTime =
10;
Display received data. Choose "preview" to display the first few frames of decoded data, or "all" to display all received data. If you choose "none", the example does not display decoded data.
displayDecodedData ="preview" ;% Select the amount of decoded data to display prmQPSKReceiver = sdrQPSKReceiverInit(SDRName, Address, sampleRate, SDRCenterFrequency, ... SDRGain, SDRStopTime, CFCAlgorithm, radioStatus)
prmQPSKReceiver = struct with fields:
Fs: 8000000
ModulationOrder: 4
Interpolation: 2
Decimation: 1
Rsym: 4000000
Tsym: 2.5000e-07
CFCAlgorithm: "FFT-Based"
BarkerCode: [1 1 1 1 1 -1 -1 1 1 -1 1 -1 1]
BarkerLength: 13
HeaderLength: 26
Message: 'Hello world'
MessageLength: 16
NumberOfMessage: 100
PayloadLength: 11200
FrameSize: 5613
FrameTime: 0.0014
RolloffFactor: 0.5000
ScramblerBase: 2
ScramblerPolynomial: [1 1 1 0 1]
ScramblerInitialConditions: [0 0 0 0]
RaisedCosineFilterSpan: 10
DesiredPower: 2
AveragingLength: 50
MaxPowerGain: 60
MaximumFrequencyOffset: 20000
PhaseRecoveryLoopBandwidth: 0.0100
PhaseRecoveryDampingFactor: 1
TimingRecoveryLoopBandwidth: 0.0100
TimingRecoveryDampingFactor: 1
TimingErrorDetectorGain: 5.4000
PreambleDetectionThreshold: 0.8000
BerMask: [7700×1 double]
Platform: "B210"
Address: "30F597A"
IsPluto: 0
IsRadioRxAvailable: 1
MasterClockRate: 16000000
USRPCenterFrequency: 915000000
USRPGain: 50
USRPFrontEndSampleRate: 8000000
USRPDecimationFactor: 2
USRPFrameLength: 11226
SDRFrameTime: 0.0014
EnableBackgroundReception: 1
StopTime: 10
Clear the MATLAB™ workspace whenever you modify the SDR settings to ensure the receiver reinitializes correctly.
Code Architecture
The function runSDRQPSKReceiver implements the QPSK receiver using two System objects:
Either comm.SDRuReceiver for USRP or comm.SDRRxPluto for ADALM-PLUTO to receive the signal over the air.
QPSKReceiverto decode the received data.
USRP/PLUTO Receiver
The host computer communicates with the USRP radio using comm.SDRuReceiver and with the ADALM-PLUTO radio using the comm.SDRRxPluto System object.
QPSK Receiver
The QPSK Receiver component receives and decodes the original transmitted message. The QPSK receiver component consists of six subcomponents. Each subcomponent uses one or more system objects internally.
Automatic Gain Control (AGC): Sets output power to a level that keeps the equivalent gains of the phase and timing error detectors constant over time. The AGC precedes the Raised Cosine Receive Filter so it can measure signal amplitude with an oversampling factor of two, improving estimate accuracy.
Coarse frequency compensation: Uses a correlation-based algorithm to roughly estimate the frequency offset and then compensate for it. The estimated coarse frequency offset is averaged so that fine frequency compensation is allowed to lock/converge. Hence, the coarse frequency offset is estimated using a
comm.CoarseFrequencyCompensatorSystem object and an averaging formula; the compensation is performed using acomm.PhaseFrequencyOffsetSystem object.Timing recovery: Performs timing recovery with closed-loop scalar processing to overcome the effects of delay introduced by the channel, using a
comm.SymbolSynchronizerSystem object. The object implements a PLL to correct the symbol timing error in the received signal. The rotationally-invariant Gardner timing error detector is chosen for the object in this example; thus, timing recovery can precede fine frequency compensation. The input to the object is a fixed-length frame of samples. The output of the object is a frame of symbols whose length can vary due to bit stuffing and stripping, depending on actual channel delays.Fine frequency compensation: Performs closed-loop scalar processing and compensates for the frequency offset accurately, using a
comm.CarrierSynchronizerSystem object. The object implements a phase-locked loop (PLL) to track the residual frequency offset and the phase offset in the input signal.Frame Synchronization: Performs frame synchronization and, also, converts the variable-length symbol inputs into fixed-length outputs, using a
FrameSynchronizerSystem object. The object has a secondary output that is a boolean scalar indicating if the first frame output is valid.Data decoder: Performs phase ambiguity resolution and demodulation. Also, the data decoder compares the regenerated message with the transmitted one and calculates the BER.
Execution and Results
To ensure data reception, first start the QPSK Transmitter with Software-Defined Radio example.
if prmQPSKReceiver.IsRadioRxAvailable [BER, overflow, output] = runSDRQPSKReceiver(prmQPSKReceiver, displayDecodedData); fprintf('Error rate is = %f.\n', BER(1)); fprintf('Number of detected errors = %d.\n', BER(2)); fprintf('Total number of compared samples = %d.\n', BER(3)); fprintf('Total number of overflows = %d.\n', overflow); else fprintf('The receiver of the radio with address, %s, is not available.\n', Address); end
Hello world 000 Hello world 001 Hello world 002 Hello world 003 Hello world 004 Hello world 005 Hello world 006 Hello world 007 Hello world 008 Hello world 009 Hello world 010 Hello world 011 Hello world 012 Hello world 013 Hello world 014 Hello world 015 Hello world 016 Hello world 017 Hello world 018 Hello world 019 ... ...
Error rate is = 0.000000.
Number of detected errors = 0.
Total number of compared samples = 54870200.
Total number of overflows = 0.
When you run the example, the receiver decodes messages and displays a preview of the received data. The BER information appears at the end of execution.
The receiver calculates BER even before all adaptive components converge, which produces a high initial BER value. Once the transient period ends, the receiver estimates the transmitted frame correctly and BER drops dramatically.
Because the simulation duration is short to keep execution time reasonable, the initial high-BER period significantly affects the overall results. To obtain lower BER values, increase the SDRStopTime
Troubleshooting
The gain behavior of ADALM-PLUTO and different USRP RF cards varies considerably. Thus, the gain setting in the transmitter and receiver defined in this example may not be well-suited for your RF cards. If the message is not properly decoded by the receiver system, you can vary the gain of the source signals in the SDR Transmitter and Receiver System objects by changing the
SDRGainvalue.The preamble detector threshold also affects message decoding. If you repeatedly receive distorted messages, increase the preamble detector threshold. A higher threshold helps the receiver correctly detect the preamble before decoding the header and message payload. If the receiver does not display any messages, decrease the threshold in the receiver initialization file to make preamble detection less restrictive.
A large relative frequency offset between the transmit and receive radios can prevent the receiver from decoding the message correctly. To compensate, see these examples Frequency Offset Calibration Transmitter with USRP Hardware and Frequency Offset Calibration Receiver with USRP Hardware
References
[1] Rice, Michael. Digital Communications - A Discrete-Time Approach. 1st ed. New York, NY: Prentice Hall, 2008.








