Main Content

DVB-S2 Receiver Using Software-Defined Radio

This example shows how to capture Digital Video Broadcasting Satellite Second Generation (DVB-S2) waveforms using the software-defined radio (SDR) device. The example then shows you how to perform synchronization, demodulation, and decoding of the received waveform, and measure the packet error rate (PER). To generate and transmit DVB-S2 waveforms, see the DVB-S2 Transmitter Using Software-Defined Radio example, and configure your test environment with:

  • Two SDR platforms connected to the same host computer. You must run two MATLAB® sessions, one for transmission and another for reception.

  • Two SDR platforms connected to different host computers. You must run a MATLAB session on each, one for transmission and another for reception.

Introduction

For this example, use the comm.SDRuReceiver, basebandReceiver, or sdrrx System object™ to receive data corrupted by over-the-air transmission at a sample rate of 2 Msps. The receiver design consists of matched filtering, symbol timing synchronization, frame synchronization, and carrier synchronization. To decode the physical layer (PL) frames, the receiver recovers the physical layer transmission parameters such as modulation scheme, code rate, and forward error correction (FEC) frame type from the PL header. To regenerate the input bit stream, receiver decodes the baseband (BB) header. Every baseband frame is a concatenation of user packets. The receiver returns the cyclic redundancy check (CRC) status of each packet is returned along with the decoded bits, and then measures the PER.

If you don't have an SDR device to capture the waveform, this example supports importing a file with a captured waveform.

This diagram summarizes the reception process.

For details on receiver design, see the DVB-S2 Link Simulation with RF Impairments and Corrections example.

This example supports these SDRs for capturing the waveform.

  • ADALM-PLUTO (requires Communications Toolbox™ Support Package for Analog Devices® ADALM-PLUTO Radio)

  • USRP™ B200/B210/N200/N210/USRP2 (requires Communications Toolbox Support Package for USRP™ Radio)

  • USRP™ N3xx/X3xx/X4xx (requires Wireless Testbench™ Support Package for NI™ USRP Radios)

Example Setup

To receive a waveform off the air, set useSDR to true. To import a waveform from a MAT file, set useSDR to false.

useSDR = false;

Specify the filename of a precaptured waveform to the fileName variable.

fileName = "capturedDVBS2Waveform.mat";

If you set useSDR to true, configure the variables required for SDR reception.

if useSDR
    rxsim.DeviceName = "B200";
    rxsim.RadioCenterFrequency = 915e6;
    rxsim.RadioGain = 20;
end

Initialize Receiver Parameters

At the receiver, you first perform DC offset compensation, followed by automatic gain control (AGC), symbol timing synchronization, and then frame synchronization, in order. The receiver algorithms include coarse and fine frequency impairment correction algorithms. The preferred loop bandwidth for symbol timing and coarse frequency compensation depends on the Es/No setting. If the captured signal is buried under noise, you can reduce the loop bandwidth to filter out more noise during acquisition. The number of frames required for the symbol synchronization and frame synchronization depends on the loop bandwidth setting.

Set rxParams.symbSyncLock to ceil(1e5/rxParams.plFrameSize) for signals heavily corrupted by noise. For signals whose SNR is less than 1 dB, set rxParams.frameSyncLock to a value in the range of [5, 15] frames. Set these fields of the rxParams structure for synchronization processing. Set valid values for fecFrame, modCod, Fsamp, and Rsym, for proper capture and validation of the demodulated signal.

fecFrame = "short";                             % DVB-S2 FECFrame type
modCod = 24;                                    % 32APSK 3/4
Fsamp = 2e6;                                    % Sampling rate in samples per second
Rsym = 1e6;                                     % Symbol rate in symbols per second
sps = Fsamp/Rsym;

rxParams = getRxParams(fecFrame,modCod);
rxParams.carrSyncLoopBW            = 4e-4;      % Coarse frequency estimator loop bandwidth normalized by symbol rate
rxParams.symbSyncLoopBW            = 1e-4;      % Symbol timing synchronizer loop bandwidth normalized by symbol rate
rxParams.symbSyncLock              = 1;         % Number of frames required for symbol timing error convergence
rxParams.frameSyncUsePilots = modCod < 6;
rxParams.sps = sps;

Capture DVB-S2 Waveform Using SDR

Discover radio(s) connected to your computer. This example uses the first SDR radio found using the rxsim.DeviceName and findsdru function. Check if the radio is available and record the radio type. Initialize sdrrx, basebandReceiver, or comm.SDRuReceiver System object. Set the platform, center frequency, sample rate, gain, and other relevant properties. Receive the DVB-S2 waveform over-the-air using the SDR device.

numFrames = 50;                                                  % Number of PL frames to capture
enableBurstMode       = true;
numFramesInBurst      = numFrames;
if useSDR
    if matches(rxsim.DeviceName,"Pluto")
        radioRx = sdrrx("Pluto");
        radioRx.RadioID               = "usb:0";
        radioRx.CenterFrequency       = rxsim.RadioCenterFrequency;
        radioRx.BasebandSampleRate    = Fsamp;
        radioRx.GainSource            = "Manual";
    elseif matches(rxsim.DeviceName,"N3xx/X3xx/X410")
        savedRadioConfigurations = radioConfigurations;
        savedRadioConfigurationNames = [string({savedRadioConfigurations.Name})];
        % Specify the index of the saved radio configuration to be utilized
        % as the receiver
        radioIndex = 1;
        radio = savedRadioConfigurationNames(radioIndex);
        if ~exist("bbrx","var")
            radioRx = basebandReceiver(radio);
        end        
        radioRx.RadioGain = rxsim.RadioGain;
        radioRx.SampleRate = Fsamp;
        radioRx.CaptureDataType = "double";
        radioRx.CenterFrequency = rxsim.RadioCenterFrequency;
    else
        connectedRadios = findsdru;
        rIdx = find(strcmp(rxsim.DeviceName,{connectedRadios.Platform}));
        if strcmp(connectedRadios(rIdx).Status,"Success")
            usrpRx.Platform = connectedRadios(rIdx).Platform;
            switch usrpRx.Platform
                case {'B200','B210'}
                    usrpRx.SerialNum = connectedRadios(rIdx).SerialNum;
                    usrpRx.MasterClockRate = 20e6;
                case 'N200/N210/USRP2'
                    usrpRx.IPAddress = connectedRadios(rIdx).IPAddress;
                    usrpRx.MasterClockRate = 100e6;
                otherwise
                    error("%s\n","Unsupported USRP device");
            end
        end
    
    switch usrpRx.Platform
        case {'B200','B210'}
            radioRx = comm.SDRuReceiver( ...
                Platform         =    usrpRx.Platform, ...
                SerialNum        =    usrpRx.SerialNum, ...
                CenterFrequency  =    rxsim.RadioCenterFrequency, ...
                MasterClockRate  =    usrpRx.MasterClockRate, ...
                DecimationFactor =    usrpRx.MasterClockRate/Fsamp);
        case 'N200/N210/USRP2'
            radioRx = comm.SDRuReceiver( ...
                Platform         =   usrpRx.Platform, ...
                IPAddress        =   usrpRx.IPAddress, ...
                CenterFrequency  =   rxsim.RadioCenterFrequency, ...
                MasterClockRate  =   usrpRx.MasterClockRate, ...
                DecimationFactor =   usrpRx.MasterClockRate/Fsamp);      
    end
    end
    if matches(rxsim.DeviceName,"N3xx/X3xx/X410")
        rxDuration = numFrames*(rxParams.plFrameSize*sps)/radioRx.SampleRate;
        [rxIn,~] = capture(radioRx,milliseconds(rxDuration*1e3));
    else
        radioRx.Gain                 = rxsim.RadioGain;                            % In dB
        radioRx.OutputDataType       = "double";
        radioRx.SamplesPerFrame      = rxParams.plFrameSize*sps;
        if enableBurstMode
            radioRx.EnableBurstMode  = enableBurstMode;
            radioRx.NumFramesInBurst = numFramesInBurst;
        end
        disp(radioRx)
        rxLength   = numFrames*radioRx.SamplesPerFrame;
        rxIn       = zeros(rxLength,1) + 1i*zeros(rxLength,1);
        for l = 1:numFrames
            [rxIn((l-1)*radioRx.SamplesPerFrame+1:l*radioRx.SamplesPerFrame),numSamps,overrun] = radioRx();
            if overrun && ~enableBurstMode
                fprintf("Overrun detected in loop #%d\n",l);
            end
        end
        release(radioRx);
    end    

Import Waveform from File

This section loads the DVB-S2 data from a MAT file.

else
    fprintf("Reading DVB-S2 IQ data from a captured file\n")
    load(fileName) 
end
Reading DVB-S2 IQ data from a captured file
rxIn = rxIn./(max(abs(rxIn)));
rxParams.initialTimeFreqSync = numFrames;
rxParams.totalSyncFrames = numFrames;

Visualize Received Waveform

Visualize the spectrum of the captured waveform and its constellation.

specAn = spectrumAnalyzer(SampleRate=Fsamp);
specAn(rxIn(1:100000));

rxConst = comm.ConstellationDiagram(Title="Received data", ...
AxesLimits=[-1 1], ...
ShowReferenceConstellation=false, ...
SamplesPerSymbol=rxParams.sps);
rxConst(rxIn(1:10000))

Initialize Receiver Processing System Objects

Create a time and coarse frequency synchronization System object by using the HelperDVBS2TimeFreqSynchronizer helper object. Initialize the comm.AGC, dsp.DCBlocker, and comm.ConstellationDiagram System objects.

% Create symbol timing and coarse frequency synchronization System object
% by using HelperDVBS2Synchronizer helper object
timeFreqSync = HelperDVBS2Synchronizer( ...
    CarrSyncLoopBW = rxParams.carrSyncLoopBW, ...
    SymbSyncLoopBW = rxParams.symbSyncLoopBW, ...
    SamplesPerSymbol = sps, ...
    DataFrameSize = rxParams.xFecFrameSize);

% Create frame synchronization System object by using
% HelperDVBS2FrameSynchronizer helper object
if strcmp(fecFrame,"normal")
    numPilotBlks = 8;
else
    numPilotBlks = 2;
end
frameSync = HelperDVBS2FrameSynchronizer( ...
    UsePilots = rxParams.frameSyncUsePilots, ...
    PLFrameLength = rxParams.plFrameSize, ...
    NumOfPilotBlocks = numPilotBlks);

agc = comm.AGC(AveragingLength=2000,AdaptationStepSize = 0.001);

dcBlock = dsp.DCBlocker(Algorithm="FIR",Length=2000);

syncConst = comm.ConstellationDiagram(Title="Synchronized data", ...
    AxesLimits=[-2 2], ...
    ShowReferenceConstellation = false);

coarseCFOEstMinFrames = 2; %floor(4/(rxParams.carrSyncLoopBW*length(rxParams.pilotInd)));

% Initialize error computing and data indexing parameters
[numFramesLost,pktsErr,bitsErr,pktsRec,dataStInd,stIdx] = deal(0);

% Variables for storing symbol synchronization output length, estimated coarse
% frequency offset, average coarse frequency offset, and
% starting index for every PL frame
[symSyncOutLen,cCFOEst,cCFOEstMean,syncIndex] = deal([]);

% Boolean variable that indicates whether the simulation has reached the last frame,
% and whether coarse frequency offset tracking has converged.
[isLastFrame,isCoarseFreqLocked] = deal(false);

% Counter to track the number of PL frames used for fine frequency
% offset estimation
numFreqEst = 0;
plFrameSize = rxParams.plFrameSize;

% Initialize FSM variables
% Use the variables to denote current state of receiver
% STR - Symbol Timing Recovery, FS - Frame Synchronization,
% CFL - Coarse Frequency Loop, FFS - Fine Frequency Synchronization,
% PS  - Phase Synchronization, FPS - Fine Phase Synchronization
% PLR - PL Frame Recovery
stateVal = num2cell([1 2 3 4 5 6 7]);
[STR, FS, CFL, FFS, PS, FPS, PLR] = stateVal{:};
state = STR;
activeState = [true false false false false false false]';
headerDataDisplayCounter = 0;
streamFormat = "packetized";
rxParams.fineFreqEstTemp = zeros(numFrames,1);

Synchronization and Data Recovery

To synchronize the received data and recover the input bit stream, process the distorted DVB-S2 waveform samples one frame at a time by following these steps.

  1. Apply DC offset compensation to remove any DC components.

  2. Apply AGC to normalize the input signal amplitude.

  3. Apply matched filtering, outputting at a rate of 2 samples per symbol.

  4. Apply symbol timing synchronization using the Gardner timing error detector (TED) with an output generated at the symbol rate. The Gardner TED is not data-aided, so you can perform before carrier synchronization.

  5. Apply frame synchronization to detect the start of frame and to identify the pilot positions.

  6. Estimate and apply coarse frequency offset correction.

  7. Estimate and apply fine frequency offset correction.

  8. Estimate and compensate for residual carrier frequency and phase noise.

  9. Decode the PL header and compute the transmission parameters.

  10. Demodulate and decode the PL frames.

  11. Perform CRC check on the BB header. If the check passes, recover the header parameters.

  12. Regenerate the input stream of data or packets from BB frames.

while stIdx < length(rxIn)

    % Use one DVB-S2 PL frame for each iteration.
    endIdx = stIdx + rxParams.plFrameSize*rxParams.sps;

    % In the last iteration, consider all the remaining samples in the received
    % waveform.
    isLastFrame = endIdx > length(rxIn);
    endIdx(isLastFrame) = length(rxIn);
    rxData = rxIn(stIdx+1:endIdx);

    % Apply DC offset compensation, AGC, matched filtering, symbol timing synchronization, frame
    % synchronization, and coarse frequency offset compensation.
    syncIn = dcBlock(rxData);
    syncIn = agc(syncIn)/sps;
    [coarseFreqSyncOut,phEst] = timeFreqSync(syncIn,syncIndex,isCoarseFreqLocked);
    coarseCFOEst = diff(phEst(1:sps:end)/(2*pi));
    cCFOEst = [cCFOEst;coarseCFOEst];
    switch state
        case STR
            symSyncOutLen = [symSyncOutLen;length(coarseFreqSyncOut)];
            if any(abs(diff(symSyncOutLen(1:rxParams.frameCount-1))) > 5)
                error("Symbol timing synchronization failed. The loop will not " + ...
                    "converge. No frame will be recovered. Update the symbSyncLoopBW " + ...
                    "parameter according to the EsNo setting for proper loop convergence.");
            end
            if rxParams.frameCount >= rxParams.symbSyncLock
                state = FS;
                fprintf("\nPerforming frame synchronization ...\n");
            end
        case FS
            activeState(FS) = true;
            if ~isempty(syncIndex)
                state = CFL;
                fprintf("\nPerforming coarse frequency synchronization ...\n");
            end
        case CFL
            activeState(CFL) = true;
            cCFOEstMean=[cCFOEstMean;mean(coarseCFOEst)]; %#ok<*AGROW>
            % Check for FLL convergence based on estimated coarse frequency
            % offset values across frames
            if length(cCFOEstMean) > coarseCFOEstMinFrames
                diffVal = diff(abs(cCFOEstMean));
                if all(abs(diffVal(end-1:end)) < 1e-2)
                    isCoarseFreqLocked = true;
                    state = FFS;
                    figure;
                    plot(cCFOEst*Rsym)
                    grid on
                    ylabel("Estimated coarse frequency offset (Hz)");
                    xlabel("Data Samples")
                    title("Coarse Frequency Locked Loop Characteristics")
                    fprintf("\nPerforming fine frequency synchronization ...\n");
                elseif rxParams.frameCount == numFrames
                    fprintf("%s\n",["Coarse frequency error estimation has either failed or it did not meet " ...
                        "convergence criteria. Try analyzing the coarse FLL characteristics from the displayed figure." ...
                        "If the CFO estimation (FLL tracking) across samples looks noisy but trends towards the correct estimation, "  ...
                        "try reducing carrSyncLoopBW and increasing coarseCFOEstMinFrames. Ensure that numFrames provides " + ...
                        "enough frames for processing. If the CFO estimation across samples is incorrect, examine syncIndex output. " + ...
                        "Since FLL uses pilots, syncIndex must be accurate for proper estimation"]);
                end
            end
        case FFS
            activeState(FFS) = true;
            if rxParams.fineFreqCorrVal ~= 0
                rxParams.fineFreqEstTemp(1:end-1) = rxParams.fineFreqEstTemp(2:end);
                rxParams.fineFreqEstTemp(end) = freqEst;
                numFreqEst = numFreqEst+1;
            end
            % Check whether the normalized fine frequency offset estimation
            % has converged to within an order of 1e–5.
            if numFreqEst>=5
                cg = abs(diff(rxParams.fineFreqEstTemp(end-numFreqEst+1:end)));
                if all(cg(end-2:end) < 1e-4)
                    state = PS;
                    activeState(FFS) = false;
                    fprintf("Estimated carrier frequency offset in Hz = %f\n",(coarseCFOEst(end)+freqEst).*Rsym);
                    fprintf("\nPerforming phase synchronization ...\n");
                elseif rxParams.frameCount == numFrames
                    fprintf("%s\n","Fine frequency error estimation has either failed or it did not meet " + ...
                        "convergence criteria. Analyze rxParams.fineFreqEstTemp to check whether the value " + ...
                        "of (coarseCFOEst(end) + freqEst) * Rsym is approaching the actual CFO. If the " + ...
                        "estimation is trending in the right direction but the simulation has reached the final frame, " + ...
                        "increase numFrames to allow more frames for convergence. If the estimation " + ...
                        "appears incorrect, examine the coarse FLL estimation. After coarse correction, the residual " + ...
                        "normalized CFO should be less than 2% of the symbol rate.");
                end
            end
        case PS
            activeState(PS) = true;
            if rxParams.prevPhaseEst ~= 0
                state = PLR;
                rxParams.totalSyncFrames = rxParams.frameCount;
                fprintf("\nPerforming PL frame demodulation and decoding  ...\n");
            end
        case PLR
            activeState(PLR) = true;
    end
    if ~isempty(rxParams.cfBuffer)
        fineFreqIn = [rxParams.cfBuffer; coarseFreqSyncOut(1:rxParams.plFrameSize-length(rxParams.cfBuffer))];
    end
    if ~isempty(syncIndex)
        rxParams.cfBuffer = coarseFreqSyncOut(syncIndex:end);
    end
    if activeState(FS)
        syncIndex = frameSync(coarseFreqSyncOut);
    end
    if activeState(FFS)
        rxParams.fineFreqCorrVal = HelperDVBS2FineFreqEst( ...
            fineFreqIn(rxParams.pilotInd),rxParams.numPilots, ...
            rxParams.refPilots,rxParams.fineFreqCorrVal);
        % Normalize the frequency estimate by the input symbol rate
        % freqEst = angle(R)/(pi*(N+1)), where N (18) is the number of elements
        % used to compute the mean of auto correlation (R) in
        % HelperDVBS2FineFreqEst.
        freqEst = angle(rxParams.fineFreqCorrVal)/(pi*(19));
    end
    if activeState(PS)
        % Generate the symbol indices using frameCount and plFrameSize.
        % Subtract 2 from the rxParams.frameCount because the buffer used to get one
        % PL frame introduces a delay of one to the count.
        ind = (rxParams.frameCount-2)*plFrameSize:(rxParams.frameCount-1)*plFrameSize-1;
        phErr = exp(-1j*2*pi*freqEst*ind);
        fineFreqOut = fineFreqIn.*phErr(:);
        % Estimate the phase error estimation by using the HelperDVBS2PhaseEst
        % helper function.
        [phEstRes,prevPhaseEstTemp] = HelperDVBS2PhaseEst( ...
            fineFreqOut,rxParams.refPilots,rxParams.prevPhaseEst,rxParams.pilotInd);
        if rxParams.prevPhaseEst ~= 0
            phaseCompOut = HelperDVBS2PhaseCompensate(rxParams.ffBuffer, ...
                rxParams.pilotEst,rxParams.pilotInd,phEstRes(2));
        end
        rxParams.ffBuffer = fineFreqOut;
        rxParams.pilotEst = phEstRes;
        rxParams.prevPhaseEst = prevPhaseEstTemp;
    end
    if activeState(PLR)  % Data valid signal
        % Decode the PL header by using the dvbsPLHeaderRecover
        % function
        syncOut = phaseCompOut/sqrt(mean(abs(phaseCompOut).^2));
        rxPLHeader = syncOut(1:90);
        phyParams = dvbsPLHeaderRecover(rxPLHeader,Mode="DVB-S2/S2X regular");
        M = phyParams.ModulationOrder;
        R = eval(phyParams.LDPCCodeIdentifier);
        fecFrame = phyParams.FECFrameLength;
        pilotStat = phyParams.HasPilots;
        xFECFrameLen = fecFrame/log2(M);
        % Validate the decoded PL header.
        if M ~= rxParams.modOrder || abs(R-rxParams.codeRate) > 1e-3 || ...
                fecFrame ~= rxParams.cwLen || ~pilotStat
            fprintf("Pl frame number %d , %s\n",rxParams.frameCount, ...
                "PL header decoding failed")
        else                                                                % Demodulation and decoding
            if ~headerDataDisplayCounter
                fprintf("%s\n","Physical layer header detection summary")
                detPLParams = generatePLParamsTable(M,R,fecFrame,pilotStat)
                headerDataDisplayCounter = headerDataDisplayCounter + 1;
            end
            rxFrame = syncOut(1:plFrameSize);
            % Estimate noise variance by using
            % HelperDVBS2NoiseVarEstimate helper function.
            nVar = HelperDVBS2NoiseVarEstimate(rxFrame,rxParams.pilotInd,...
                rxParams.refPilots,false);
            snr_dB = 10*log10(1/nVar);
            fprintf("PL frame number = %d\n",rxParams.frameCount)
            fprintf("Estimated SNR in dB = %f\n",snr_dB)
            % Recover the input bit stream by using
            % dvbs2BitRecover function
            % Recover the input bit stream by using
            % dvbs2BitRecover function
            [decBitsTemp,isFrameLost,pktCRC]  = dvbs2BitRecover(rxFrame,nVar);
            decBits = decBitsTemp{:};
            if ~isLastFrame
                pktsErr = pktsErr + numel(pktCRC{:}) - sum(pktCRC{:});
                pktsRec = pktsRec + numel(pktCRC{:});
            end
            if ~isFrameLost
                fprintf("%s\n","BB header decoding passed")
                if isempty(pktCRC{1})
                    streamFormat = "continuous";
                else
                    streamFormat = "packetized";
                end
            else
                fprintf("%s\n","BB header decoding failed")
            end
            % Compute the number of frames lost. Consider CRC failure of the baseband header
            % as a frame loss.
            numFramesLost = isFrameLost + numFramesLost;
            fprintf("Total number of frames lost = %1d\n",numFramesLost)
        end
    end
    stIdx = endIdx;
    rxParams.frameCount = rxParams.frameCount + 1;
end
Performing frame synchronization ...
Performing coarse frequency synchronization ...

Figure contains an axes object. The axes object with title Coarse Frequency Locked Loop Characteristics, xlabel Data Samples, ylabel Estimated coarse frequency offset (Hz) contains an object of type line.

Performing fine frequency synchronization ...
Estimated carrier frequency offset in Hz = 3282.922363
Performing phase synchronization ...
Performing PL frame demodulation and decoding  ...
Physical layer header detection summary
detPLParams=1×4 table
    Modulation    Code Rate    FEC Frame    Pilot Status
    __________    _________    _________    ____________

     "32APSK"       "3/4"       "short"        "true"   

PL frame number = 16
Estimated SNR in dB = 14.958315
BB header decoding passed
Total number of frames lost = 0
PL frame number = 17
Estimated SNR in dB = 15.665258
BB header decoding passed
Total number of frames lost = 0
PL frame number = 18
Estimated SNR in dB = 14.788181
BB header decoding passed
Total number of frames lost = 0
PL frame number = 19
Estimated SNR in dB = 15.360274
BB header decoding passed
Total number of frames lost = 0
PL frame number = 20
Estimated SNR in dB = 16.706640
BB header decoding passed
Total number of frames lost = 0

Visualization and Error Logs

Plot the constellation of the synchronized data and compute PER.

if exist('rxFrame','var')
    scatterplot(rxFrame)
end

Figure Scatter Plot contains an axes object. The axes object with title Scatter plot, xlabel In-Phase, ylabel Quadrature contains a line object which displays its values using only markers. This object represents Channel 1.

% Error metrics display
% For GS and TS packetized streams
if strcmp(streamFormat,"packetized")
    if pktsRec == 0
        fprintf("All frames are lost. No packets are retrieved from BB frames.")
    else
        per = pktsErr/pktsRec;
fprintf("PER: %1.2e\n",per)
    end
end
PER: 0.00e+00

Further Exploration

  • Transmit a DVB-S2 waveform by using the DVB-S2 Transmitter Using Software-Defined Radio example. You can then decode the waveform using this example. In the companion example, try changing the FECFrame and MODCOD, and observe the detected PL parameters decoded in this example.

  • For details on how to configure the synchronization parameters of the rxParams for other configurations, see the Further Exploration section of DVB-S2 Link Simulation with RF Impairments and Corrections example.

SDR Troubleshooting

Supporting Files

The example uses these helper functions and data file:

  • HelperDVBS2Synchronizer.m: Perform matched filtering, symbol timing synchronization, frame synchronization, and coarse frequency estimation and correction

  • HelperDVBS2FrameSynchronizer.m: Perform frame synchronization and detect the start of frame

  • HelperDVBS2FineFreqEst.m: Estimate fine frequency offset

  • HelperDVBS2PhaseEst.m: Estimate carrier phase offset

  • HelperDVBS2PhaseCompensate.m: Perform carrier phase compensation

  • HelperDVBS2NoiseVarEstimate.m: Estimate noise variance of received data

  • capturedDVBS2Waveform.mat: DVB-S2 IQ data captured using DVB-S2 Transmitter Using Software-Defined Radio example and SDRs.

References

  1. ETSI Standard EN 302 307-1 V1.4.1(2014-11). Digital Video Broadcasting (DVB); Second Generation Framing Structure, Channel Coding and Modulation Systems for Broadcasting, Interactive Services, News Gathering and other Broadband Satellite Applications (DVB-S2).

  2. ETSI Standard TR 102 376-1 V1.2.1(2015-11). Digital Video Broadcasting (DVB); Implementation Guidelines for the Second Generation System for Broadcasting, Interactive Services, News Gathering and other Broadband Satellite Applications (DVB-S2).

Local Functions

function rxParams = getRxParams(fecFrame,modCod)
% Receiver parameters generation

[modOrder,codeRate,cwLen] = satcom.internal.dvbs.getS2PHYParams(modCod,fecFrame);

dataLen = cwLen/log2(modOrder);

% Pilot sequence and indices generation
slotLen = 90;
pilotBlkFreq = 16;                                                    % In slots
numPilotBlks = floor(dataLen/(slotLen*pilotBlkFreq));
if floor(dataLen/(slotLen*16)) == dataLen/(slotLen*pilotBlkFreq)
    numPilotBlks = numPilotBlks - 1;
end
pilotLen = numPilotBlks*36;                                           % one pilot block contains 36 pilot symbols
frameSize = dataLen + pilotLen + slotLen;
plScrambIntSeq = satcom.internal.dvbs.plScramblingIntegerSequence(0);
cMap = [1 1j -1 -1j].';
cSeq = cMap(plScrambIntSeq+1);
[~, pilotInd] = satcom.internal.dvbs.pilotBlock(numPilotBlks);

rxParams.plFrameSize = frameSize;
rxParams.xFecFrameSize = dataLen;
rxParams.modOrder = modOrder;
rxParams.codeRate = codeRate;
rxParams.cwLen = cwLen;
rxParams.frameCount = 1;
rxParams.numPilots = numPilotBlks;
rxParams.pilotInd = pilotInd + slotLen;
rxParams.refPilots = (1+1j)/sqrt(2).*cSeq(pilotInd);
rxParams.cfBuffer = [];
rxParams.ffBuffer = complex(zeros(frameSize, 1));
rxParams.pilotPhEst = zeros(numPilotBlks+1, 1);
[rxParams.prevPhaseEst, rxParams.fineFreqCorrVal] = deal(0);
rxParams.syncIndex = 1;
end
function tbl =  generatePLParamsTable(M,R,fecFrame,pilotStat)
modScheme = ["QPSK" "8PSK" "16APSK" "32APSK"];
Modulation = modScheme(log2(M)-1);
[n,d] = rat(R);
CodeRate = strcat(string(n),"/",string(d));
if fecFrame == 64800
    FECFrame = "normal";
else
    FECFrame = "short";
end
if pilotStat
    PilotStatus = "true";
else
    PilotStatus = "false";
end
tbl = table(Modulation,CodeRate,FECFrame,PilotStatus);
tbl = renamevars(tbl,["Modulation","CodeRate","FECFrame", "PilotStatus"],["Modulation","Code Rate","FEC Frame", "Pilot Status"]);
end

See Also

|

Topics