Main Content

QPSK Receiver Using Software-Defined Radio

R2026b
Since R2025a

This 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

Flowchart to configure an SDR as a QPSK receiver. The first box, labeled Configure SDR, includes options: Select SDR Type, Select SDR Name, and Select SDR Address. An arrow points to the next box, Configure Signal Properties, with options: Center Frequency (Hz), Gain (dB), Sample Rate (Hz), and SDRStopTime. Another arrow leads to a box labeled sdrQPSKReceiverInit, which then points to prmQPSKReceiver

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.

  • QPSKReceiver to 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.

  1. 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.

  2. 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.CoarseFrequencyCompensator System object and an averaging formula; the compensation is performed using a comm.PhaseFrequencyOffset System object.

  3. Timing recovery: Performs timing recovery with closed-loop scalar processing to overcome the effects of delay introduced by the channel, using a comm.SymbolSynchronizer System 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.

  4. Fine frequency compensation: Performs closed-loop scalar processing and compensates for the frequency offset accurately, using a comm.CarrierSynchronizer System object. The object implements a phase-locked loop (PLL) to track the residual frequency offset and the phase offset in the input signal.

  5. Frame Synchronization: Performs frame synchronization and, also, converts the variable-length symbol inputs into fixed-length outputs, using a FrameSynchronizer System object. The object has a secondary output that is a boolean scalar indicating if the first frame output is valid.

  6. 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 SDRGain value.

  • 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.