Main Content

comm.SOQPSKDemodulator

R2026b

Demodulate signal using SOQPSK method and Viterbi algorithm

Since R2026a

Description

The comm.SOQPSKDemodulator System object™ demodulates an input signal that was modulated by using the shaped-offset quadrature phase shift keying (SOQPSK) method. The input is a baseband representation of the modulated signal. For more information about the demodulation and filtering applied, see Algorithms.

To demodulate a signal that was modulated using the SOQPSK method:

  1. Create the comm.SOQPSKDemodulator object and set its properties.

  2. Call the object with arguments, as if it were a function.

To learn more about how System objects work, see What Are System Objects?

Creation

Description

soqpskdemod = comm.SOQPSKDemodulator creates a demodulator System object to demodulate input SOQPSK signals using the Viterbi algorithm.

soqpskdemod = comm.SOQPSKDemodulator(Name=Value) sets properties using one or more name-value arguments. For example, comm.SOQPSKDemodulator(FrequencyPulse="A") specifies type A frequency pulse shaping.

example

Properties

expand all

Unless otherwise indicated, properties are nontunable, which means you cannot change their values after calling the object. Objects lock when you call them, and the release function unlocks them.

If a property is tunable, you can change its value at any time.

For more information on changing property values, see System Design in MATLAB Using System Objects.

Type of frequency pulse shaping used by the modulator to smooth the phase transitions of the modulated signal, specified as "TG", "A", or "B". For more information, see Pulse Shape Filtering.

Demodulation decision method, specified as "hard" or "approxllr".

  • When you set this property to "hard", the output Y is returned as a column vector with element values of 0 or 1. The output data type is specified by OutputDataType.

  • When you set this property to "approxllr", the output data type is the same as the input X. For the approximate log-likelihood ratio, the object generates positive values for 0s and negative values for 1s.

For more information, see SOQPSK Demodulation.

Noise variance, specified as a positive scalar or "input".

Dependencies

This property applies when you set DecisionMethod to "approxllr".

Data Types: double | single | string

Precoder initial input, specified as a binary-valued scalar or a two-element row vector. When provided as a scalar, the same value applies to both elements.

This property defines the first data symbol used by the modulator before the first call of the object, in reverse chronological order.

Initial phase offset in radians, specified as a scalar. This parameter value is the initial phase offset of the modulated waveform.

Samples per symbol, specified as a positive even integer. This property specifies the output symbol upsampling factor for each input sample.

Traceback depth for the Viterbi algorithm, specified as a positive integer representing the number of trellis branches that the Viterbi algorithm uses to construct each traceback path. For more information, see Traceback Depth and Output Delays.

Data type of the output, specified as "double", "single", or "int8".

Dependencies

This property applies when you set DecisionMethod to "hard".

This property is read-only.

Demodulator output delay, specified as a positive integer. For more information, see Traceback Depth and Output Delays.

Usage

Description

Y = soqpskdemod(X) demodulates the input signal by using the SOQPSK method.

example

Input Arguments

expand all

SOQPSK-modulated signal, specified as a column vector with a length equal to an integer multiple of the SamplesPerSymbol property.

This object accepts variable-size inputs. After the object is locked, you can change the frame size (number of rows) of the signal during simulation. For more information, see Variable-Size Signals in Code.

Data Types: double | single
Complex Number Support: Yes

Noise variance, specified as a positive scalar value.

Dependencies

This property applies when you set VarianceSource to "input", and DecisionMethod to "approxllr".

Data Types: double | single

Output Arguments

expand all

Demodulated output signal, returned as a column vector with NSamp/(NSPS) elements. NSamp is the length of input Y and NSPS is the value of SamplesPerSymbol.

To specify the output data type, use the OutputDataType property.

The output has a processing delay. For more information, see Traceback Depth and Output Delays.

Data Types: single | double | int8

Object Functions

To use an object function, specify the System object as the first input argument. For example, to release system resources of a System object named obj, use this syntax:

release(obj)

expand all

stepRun System object algorithm
releaseRelease resources and allow changes to System object property values and input characteristics
resetReset internal states of System object

Examples

collapse all

Demodulate a noisy SOQPSK-B-modulated waveform by using hard-decision processing.

Create SOQPSK modulator and demodulator objects, and a frame of random binary data. Set an EbN0 level for the AWGN channel and convert the value to SNR.

soqpskMod = comm.SOQPSKModulator(FrequencyPulse="B")
soqpskMod = 
  comm.SOQPSKModulator with properties:

        FrequencyPulse: "B"
     InitialConditions: [0 0]
    InitialPhaseOffset: 0
      SamplesPerSymbol: 8
        OutputDataType: "double"

soqpskDemod = comm.SOQPSKDemodulator(FrequencyPulse="B")
soqpskDemod = 
  comm.SOQPSKDemodulator with properties:

        FrequencyPulse: "B"
        DecisionMethod: "hard"
     InitialConditions: [0 0]
    InitialPhaseOffset: 0
      SamplesPerSymbol: 8
        TracebackDepth: 8
        OutputDataType: "double"

  Show all properties

data = randi([0 1],1e3,1);
EbNodB = 11;
snrdB = convertSNR(EbNodB,'ebno', ...
    BitsPerSymbol=2,SamplesPerSymbol=soqpskMod.SamplesPerSymbol);

Apply SOQPSK modulation, add AWGN to the modulated signal, and then demodulate the received symbols.

txOut = soqpskMod(data);
rxIn = awgn(txOut,snrdB,'measured');
rxOut = soqpskDemod(rxIn);

Account for the delay, which equals the sum of the traceback depth and the filter delay, and then calculate the number of errors. The delay equals TracebackDepth + PulseLength/2. Set the delay based on the traceback depth length and the frequency pulse type used for demodulation.

if soqpskMod.FrequencyPulse=="B"
    PulseLength = 16;    
else
    PulseLength = 8;
end
delay = soqpskDemod.TracebackDepth+PulseLength/2;

Confirm the expected delay by using the finddelay function.

delaycheck = finddelay(data,rxOut)
delaycheck = 
16
isequal(delay,delaycheck)
ans = logical
   1

numErr = sum(data(1:end-delay)~=rxOut(delay+1:end))
numErr = 
0

Shaped-offset quadrature phase shift keying (SOQPSK) modulate random bits with an SOQPSK modulator object, add AWGN, demodulate with a matching SOQPSK demodulator object, and then compute the error rate comparing hard decision and approximate LLR decision decoding. Error rate performance of the hard and approximate LLR decision decoding match because no forward error correction is included.

rng(2024)      % For repeatable runs
numBits = 1e6; % Number of input bits
bps = 2;       % Bits per symbol for SOQPSK
sps = 4;       % Samples per symbol
EbNo_dB = 8;   % Eb/No in dB

Create a column vector of random bits. Create objects for SQPSK modulation, SOQPSK hard-decision and soft-decision demodulation, and error rate computation for hard- and soft-decision. In the error rate objects, set the receive delay to the OutputDelay property of the SQPSK demodulator hard and soft decision objects, respectively.

txBits = randi([0 1],numBits,1);
mod = comm.SOQPSKModulator(SamplesPerSymbol=sps);
demod_hd = comm.SOQPSKDemodulator(SamplesPerSymbol=sps);
delay_hd = demod_hd.OutputDelay;
demod_sd = comm.SOQPSKDemodulator( ...
    SamplesPerSymbol=sps,DecisionMethod="approxllr",Variance="input");
delay_sd = demod_sd.OutputDelay;
errorRate_hd = comm.ErrorRate(ReceiveDelay=delay_hd);
errorRate_sd = comm.ErrorRate(ReceiveDelay=delay_sd);

Pass an SOQPSK modulated signal through AWGN. Demodulate the signal using the SOQPSK demodulator. Compute and display the bit error rate.

modOut = mod(txBits);
SNRdB = convertSNR(EbNo_dB,"ebno", ...
    SamplesPerSymbol=sps,BitsPerSymbol=bps);
chanOut = awgn(modOut,SNRdB,"measured");
rxBits_hard = demod_hd(chanOut);
var =10^(-SNRdB/10);
llrdemodOut = demod_sd(chanOut,var);
rxBits_llr = llrdemodOut < 0;

errorStats_hd = errorRate_hd(txBits,rxBits_hard(1:length(txBits)));
fprintf("Hard decision:\n  Error rate = %f\n  Number of errors = %d\n", ...
errorStats_hd(1),errorStats_hd(2))
Hard decision:
  Error rate = 0.000605
  Number of errors = 605
errorStats_sd = errorRate_sd(txBits,rxBits_llr(1:length(txBits)));
fprintf("Soft decision:\n  Error rate = %f\n  Number of errors = %d\n", ...
errorStats_sd(1),errorStats_sd(2))
Soft decision:
  Error rate = 0.000605
  Number of errors = 605
reset(errorRate_hd)
reset(errorRate_sd)
reset(demod_hd)
reset(demod_sd)

Option to plot BER vs Eb/No curve.

berPlot = 0;
if berPlot
    EbNoVec = -2:2:8;
    SNRdBVec = convertSNR(EbNoVec,"ebno", ...
        SamplesPerSymbol=sps,BitsPerSymbol=bps);
    errorStats_hd = zeros(length(EbNoVec),3);
    errorStats_sd = zeros(length(EbNoVec),3);
    for ii=1:length(EbNoVec)
        chanOut = awgn(modOut,SNRdBVec(ii),"measured");
        rxBits_hard = demod_hd(chanOut);
        llrdemodOut = demod_sd(chanOut,var);
        rxBits_llr = llrdemodOut < 0;
        errorStats_hd(ii,:) = errorRate_hd( ...
            txBits,rxBits_hard(1:length(txBits)));
        errorStats_sd(ii,:) = errorRate_sd( ...
            txBits,rxBits_llr(1:length(txBits)));
        reset(errorRate_hd)
        reset(errorRate_sd)
        reset(demod_hd)
        reset(demod_sd)
    end
    semilogy(EbNoVec,errorStats_hd(:,1),"--+b", ...
        EbNoVec,errorStats_sd(:,1),"-or");
    grid on;
    xlabel("E_b/N_0 (dB)");
    ylabel("BER");
    legend("hd","sd")
    title("SOQPSK BER vs Eb/No");
end

Estimate the bit error rate (BER) performance of a shaped-offset quadrature phase shift keying - telemetry group (SOQPSK-TG) with low-density parity-check (LDPC) coding over an additive white Gaussian noise (AWGN) channel.

Define a prototype matrix and block size to configure a rate 3/4 LDPC code. Create a parity-check matrix by using the ldpcQuasiCyclicMatrix function, and then use the parity-check matrix to create LDPC encoder and decoder configuration objects.

P = [
    16 17 22 24  9  3 14 -1  4  2  7 -1 26 -1  2 -1 21 -1  1  0 -1 -1 -1 -1
    25 12 12  3  3 26  6 21 -1 15 22 -1 15 -1  4 -1 -1 16 -1  0  0 -1 -1 -1
    25 18 26 16 22 23  9 -1  0 -1  4 -1  4 -1  8 23 11 -1 -1 -1  0  0 -1 -1
    9  7  0  1 17 -1 -1  7  3 -1  3 23 -1 16 -1 -1 21 -1  0 -1 -1  0  0 -1
    24  5 26  7  1 -1 -1 15 24 15 -1  8 -1 13 -1 13 -1 11 -1 -1 -1 -1  0  0
    2  2 19 14 24  1 15 19 -1 21 -1  2 -1 24 -1  3 -1  2  1 -1 -1 -1 -1  0
    ];
blockSize = 27;
pcmatrix = ldpcQuasiCyclicMatrix(blockSize,P);
cfgLDPCEnc = ldpcEncoderConfig(pcmatrix);
cfgLDPCDec = ldpcDecoderConfig(pcmatrix,"norm-min-sum");

Create System objects for SOQPSK-TG modulation and demodulation.

soqpskmod = comm.SOQPSKModulator;
soqpskdemod = comm.SOQPSKDemodulator(DecisionMethod="approxllr");
delay = soqpskdemod.OutputDelay;

Define simulation parameters, convert Eb/N0 to SNR, and initialize variables to track coded error rate results.

codeRate = 3/4;
maxnumiter = 10;
numframes = 5000;
EbNo = 3:0.5:4.5;
snr = convertSNR(EbNo,'ebno', ...
    BitsPerSymbol=2, ...
    SamplesPerSymbol=soqpskmod.SamplesPerSymbol, ...
    CodingRate=codeRate);
numErrsCoded = zeros(length(snr),1);
numBitsCoded = zeros(length(snr),1);

For each Eb/N0 setting, transmit an LDPC-encoded, SOQPSK-TG-modulated bit stream through an AWGN channel. Demodulate the signal using soft-decision (approximate LLR) output, and decode the received codewords. Use a buffer to align codewords across frame boundaries. Since SOQPSK-TG is a continuous-phase modulation with memory, the soft-decision demodulator produces outputs with a processing delay that must be accounted for when count bit errors.

for ii = 1:length(EbNo)
    numErrs = 0;
    numBits = 0;
    release(soqpskdemod);
    soqpskdemod.Variance = 10^(-snr(ii)/10);
    demBuffer = zeros(cfgLDPCEnc.BlockLength,1);
    dataBuffer = zeros(cfgLDPCEnc.NumInformationBits,1);

Simulate multiple frames by using a for loop.

    for frameCnt = 1:numframes
        data = randi([0 1],cfgLDPCEnc.NumInformationBits,1,'int8');
        encodedData = ldpcEncode(data,cfgLDPCEnc);
        modSig = soqpskmod(double(encodedData));
        rxSig = awgn(modSig,snr(ii),'measured');
        demOut = soqpskdemod(rxSig);

        % Account for demodulator delay and align codewords across frames.
        if frameCnt > 1
            demAligned = [demBuffer(delay+1:end); demOut(1:delay)];

            % Pad or truncate to match block length
            llrIn = demAligned(1:cfgLDPCEnc.BlockLength);

            rxbits = ldpcDecode(llrIn,cfgLDPCDec,maxnumiter, ...
                MinSumScalingFactor=0.75,Termination="early");

            numErrsCoded(ii) = numErrsCoded(ii) + nnz(dataBuffer ~= rxbits);
            numBitsCoded(ii) = numBitsCoded(ii) + numel(dataBuffer);
        end
        demBuffer = demOut;
        dataBuffer = data;
    end
    fprintf('SNR = %2.1f dB (Eb/No = %2.1f dB)\n', ...
        snr(ii),EbNo(ii));
    fprintf('   Coded BER: %1.6f (%d errors / %d bits)\n', ...
        numErrsCoded(ii)/max(numBitsCoded(ii),1), ...
        numErrsCoded(ii),numBitsCoded(ii));
end
SNR = -4.3 dB (Eb/No = 3.0 dB)
   Coded BER: 0.006105 (14831 errors / 2429514 bits)
SNR = -3.8 dB (Eb/No = 3.5 dB)
   Coded BER: 0.000529 (1284 errors / 2429514 bits)
SNR = -3.3 dB (Eb/No = 4.0 dB)
   Coded BER: 0.000004 (10 errors / 2429514 bits)
SNR = -2.8 dB (Eb/No = 4.5 dB)
   Coded BER: 0.000000 (0 errors / 2429514 bits)

More About

expand all

Algorithms

expand all

This implementation of the SOQPSK method conforms to the specification in IRIG Standard 106-17, Chapter 2 [1], and includes support for SOQPSK-TG, SOQPSK-A, and SOQPSK-B frequency pulse-shapes.

References

[1] Inter-Range Instrumentation Group (IRIG) Telemetry Standards, IRIG Standard 106-17, Chapter 2, July 2017.

[2] E. Perrins and M. Rice, "Reduced-Complexity Approach to Iterative Detection of Coded SOQPSK," in IEEE® Transactions on Communications, vol. 55, no. 7, pp. 1354-1362, July 2007, doi: 10.1109/TCOMM.2007.900614.

[3] E. Perrins, "FEC Systems for Aeronautical Telemetry," in IEEE Transactions on Aerospace and Electronic Systems, vol. 49, no. 4, pp. 2340-2352, OCTOBER 2013, doi: 10.1109/TAES.2013.6621820.

[4] Benedetto, S., G. Montorsi, D. Divsalar, and F. Pollara. "A Soft-Input Soft-Output Maximum A Posterior (MAP) Module to Decode Parallel and Serial Concatenated Codes." Jet Propulsion Lab TDA Progress Report (November 1996): 42–127.

[5] Viterbi, A.J. “An Intuitive Justification and a Simplified Implementation of the MAP Decoder for Convolutional Codes.” IEEE Journal on Selected Areas in Communications 16, no. 2 (February 1998): 260–64. https://doi.org/10.1109/49.661114.

Extended Capabilities

expand all

Version History

Introduced in R2026a

expand all