主要内容

DVB-S2 Waveform Transmission and Reception Using Instrument Control Toolbox

This example shows how to generate Digital Video Broadcasting Satellite Second Generation (DVB-S2) physical layer (PL) frames using the Wireless Waveform Generator App and download the generated waveform to a Keysight™ vector signal generator for over-the-air transmission using the Instrument Control Toolbox™ software. The example then captures the transmitted over-the-air signal using a Keysight signal analyzer, decodes the PL frames and analyzes the signal in MATLAB®.

Introduction

This example generates a DVB-S2 baseband waveform using the Wireless Waveform Generator app, downloads the waveform onto a Keysight vector signal generator, and transmits it over the air using the Instrument Control Toolbox. A Keysight signal analyzer then captures the data corrupted by over-the-air transmission at a sample rate of 4 Msps, after which baseband waveform analysis is performed.

Requirements

To run this example, you need:

  • Instrument Control Toolbox

  • Satellite Communications Toolbox

  • Communications Toolbox

  • Instrument Control Toolbox Support Package for Keysight (Agilent) IO Libraries and VISA Interface

  • Keysight N5182B vector signal generator

  • Keysight N9040B UXA signal analyzer

The Keysight vector signal generator device in this setup transmits DVB-S2 in-phase and quadrature phase (IQ) samples at the specified frequency and symbol rate.

This diagram summarizes the transmission, capture, and the general workflow.

Download DVB-S2 LDPC Parity Matrices Data Set

Load a MAT file containing DVB-S2 LDPC parity matrices.These are a set of matrices used in the DVB-S2 standard for error correction, and are used to encode and decode data to ensure reliable transmission over satellite.

If the MAT file is not available on the MATLAB path, use these commands to download and unzip the MAT file.

if ~exist('dvbs2xLDPCParityMatrices.mat','file')
    if ~exist('s2xLDPCParityMatrices.zip','file')
        url = 'https://ssd.mathworks.com/supportfiles/spc/satcom/DVB/s2xLDPCParityMatrices.zip';
        websave('s2xLDPCParityMatrices.zip',url);
        unzip('s2xLDPCParityMatrices.zip');
    end
    addpath('s2xLDPCParityMatrices');
end

Generate Baseband Waveform Using Wireless Waveform Generator App

In MATLAB, on the Apps tab, click the Wireless Waveform Generator app.

In the Waveform Type section, click DVB-S2. Digital Video Broadcasting Satellite Second Generation (DVB-S2) is a physical layer standard to support high-data-rate satellite communications in space.

In the left-most pane of the app, you can set the parameters for the selected waveform. For this example:

Under DVB-S2 Waveform Configuration:

  • Set Input stream format as TS

  • Set Number of streams as 1

  • Set FEC Frame as normal

  • Set MODCOD as 18

  • Set Data field length as 42960

  • Set Pilot Indication as 1

  • Set Output symbol rate (sym/s) as 1e6

Under Filtering Configuration:

  • Set Rolloff factor as 0.35

  • Set Oversampling factor as 4

  • Set Filter span (symbols) as 10

Under Bit Source:

  • Set Bit Source as PN9

  • Set Number of PL frames as 50

On the app toolstrip, click Generate.

This figure shows a DVBS2 waveform visible at baseband.

Transmit Baseband Waveform Over-the-Air Using Wireless Waveform Generator App

Download the generated signal to the RF signal generator over one of the supported communication interfaces (requires Instrument Control Toolbox). The app automatically finds the signal generator that is connected over the TCP/IP interface. On the Transmitter tab of the app, select Agilent/Keysight Signal Generator SCPI from the Driver list. Set the Center frequency (Hz) parameter to 5.5e9 and the Output power (dBm) parameter to -15. The app automatically obtains the baseband sample rate from the generated waveform. To start the transmission, click Transmit in the toolstrip.

Read IQ Data from a Signal Analyzer over TCP/IP

To read the in-phase and quadrature (IQ) data into MATLAB for analysis, configure the Keysight N9040B signal analyzer using the Instrument Control Toolbox software.

Define the instrument configuration parameters based on the signal you are measuring.

% Set parameters for the spectrum analyzer
centerFrequency = 5.5e9;
measurementTime = 800e-3;
mechanicalAttenuation = 0;
startFrequency = 5.49e9;
stopFrequency = 5.51e9;
resolutionBandwidth = 220e3;
videoBandwidth = 220e3;

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 the rxParams fields structure for synchronization processing. Set valid values for fecFrame, modCod, Fsamp, and Rsym, for proper capture and validation of the demodulated signal.

fecFrame = "normal";                            % DVB-S2 FECFrame type
modCod = 18;                                    % 32APSK 3/4
Fsamp = 4e6;                                    % Sampling rate in samples per second
Rsym = 1e6;                                     % Symbol rate in symbols per second
sps = Fsamp/Rsym;
numFrames = 50;
rxParams = getRxParams(fecFrame,modCod);
rxParams.carrSyncLoopBW            = 1e-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              = 2;         % Number of frames required for symbol timing error convergence
rxParams.frameSyncLock             = 1;         % Number of frames required for frame synchronization
rxParams.sps = sps;
% Total frames taken for symbol timing and frame synchronization to happen
rxParams.initialTimeSync = rxParams.symbSyncLock + rxParams.frameSyncLock;
rxParams.initialTimeFreqSync = numFrames;
rxParams.totalSyncFrames = numFrames;

Capture DVB-S2 Waveform Using Signal Analyzer Instrument

Perform these steps to connect to the signal analyzer. instrument:

  • Find the resource ID of the Keysight N9040B signal analyzer.

  • Connect to the instrument using the visadev interface.

  • Set the ByteOrder on the signal analyzer to match the ByteOrder used by the transmitter.

  • Set the timeout to allow sufficient time for the measurement and data transfer.

foundVISA = visadevlist;
resourceID = foundVISA(foundVISA.Model == "N9040B",:).ResourceName;
sigAnalyzerObj = visadev(resourceID);
sigAnalyzerObj.ByteOrder = "big-endian";
sigAnalyzerObj.Timeout = 20;

Reset the instrument to a known state by sending the appropriate SCPI command. Query the instrument identity to ensure the correct instrument is connected.

writeline(sigAnalyzerObj,"*RST");
instrumentInfo = writeread(sigAnalyzerObj,"*IDN?");
fprintf("Instrument identification information: %s",instrumentInfo);
Instrument identification information: Keysight Technologies,N9040B,US00091124,A.36.00_D0071

The X-Series signal and spectrum analyzers perform IQ measurements as well as spectrum measurements. In this example, you acquire time domain IQ data, visualize the data using MATLAB, and perform signal analysis on the acquired data. The SCPI commands configure the instrument and define the format of the data transfer after the measurement is complete.

% Set up signal analyzer mode to basic IQ mode
writeline(sigAnalyzerObj,":INSTrument:SELect BASIC");

% Set the center frequency
writeline(sigAnalyzerObj,strcat(":SENSe:FREQuency:CENTer ",num2str(centerFrequency)));

% Set the capture sample rate
writeline(sigAnalyzerObj,strcat(":SENSe:WAVeform:SRATe ",num2str(Fsamp)));

% Turn off averaging
writeline(sigAnalyzerObj,":SENSe:WAVeform:AVER OFF");

% Set the spectrum analyzer to take one single measurement after the trigger line goes high
writeline(sigAnalyzerObj,":INIT:CONT OFF");

% Set the trigger to external source 1 with positive slope triggering
writeline(sigAnalyzerObj,":TRIGger:WAVeform:SOURce IMMediate");
writeline(sigAnalyzerObj,":TRIGger:LINE:SLOPe POSitive");

% Set the time for which measurement needs to be made
writeline(sigAnalyzerObj,strcat(":WAVeform:SWE:TIME ",num2str(measurementTime)));

% Turn off electrical attenuation
writeline(sigAnalyzerObj,":SENSe:POWer:RF:EATTenuation:STATe OFF");

% Set the mechanical attenuation level
writeline(sigAnalyzerObj,strcat(":SENSe:POWer:RF:ATTenuation ",num2str(mechanicalAttenuation)));

% Turn IQ signal ranging to auto
writeline(sigAnalyzerObj,":SENSe:VOLTage:IQ:RANGe:AUTO ON");

% Set the endianness of returned data
writeline(sigAnalyzerObj,":FORMat:BORDer NORMal");

% Set the format of the returned data
writeline(sigAnalyzerObj,":FORMat:DATA REAL,64");

Trigger the instrument to make the measurement. Wait for the measurement operation to complete, and then read-in the waveform. Before processing the data, separate the I and Q components from the interleaved data that is received from the instrument and create a complex vector in MATLAB.

writeline(sigAnalyzerObj,"*TRG");
writeline(sigAnalyzerObj,":INITiate:WAVeform");
measureComplete = writeread(sigAnalyzerObj,"*OPC?");
writeline(sigAnalyzerObj,":READ:WAV0?");
data = readbinblock(sigAnalyzerObj,"double");

% Create the IQ vector
inphase = data(1:2:end);
quadrature = data(2:2:end);
rxWaveform = inphase+1i*quadrature;

Capture and display the information about the most recently acquired data.

writeline(sigAnalyzerObj,":FETCH:WAV1?");
signalSpec = readbinblock(sigAnalyzerObj,"double");
captureSampleRate = 1/signalSpec(1);
fprintf("Sample Rate (Hz) = %s",num2str(captureSampleRate));
Sample Rate (Hz) = 4000000
fprintf("Number of points read = %s",num2str(signalSpec(4)));
Number of points read = 3200001
fprintf("Max value of signal (dBm) = %s",num2str(signalSpec(6)));
Max value of signal (dBm) = -10.5522
fprintf("Min value of signal (dBm) = %s",num2str(signalSpec(7)));
Min value of signal (dBm) = -94.96

Visualize Received Waveform

Visualize the spectrum of the captured waveform. Transform rxwaveform into a column vector for the spectrumAnalyzer object.

rxWaveform = rxWaveform.';
specAn = spectrumAnalyzer(SampleRate=Fsamp);
specAn(rxWaveform)

Initialize Receiver Processing System Objects

After examining the received signal spectrum, proceed to initialize the receiver processing System objects required for synchronization and signal conditioning. 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.

timeFreqSync = HelperDVBS2TimeFreqSynchronizer( ...
    CarrSyncLoopBW=rxParams.carrSyncLoopBW, ...
    SymbSyncLoopBW=rxParams.symbSyncLoopBW, ...
    SamplesPerSymbol=rxParams.sps, ...
    DataFrameSize=rxParams.xFecFrameSize, ...
    SymbSyncTransitFrames=rxParams.symbSyncLock, ...
    FrameSyncAveragingFrames=rxParams.frameSyncLock);

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

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

syncConst = comm.ConstellationDiagram(Title="Synchronized data", ...
XLimits=[-2 2], ...
YLimits=[-2 2], ...
ShowReferenceConstellation = false);
[numFramesLost,pktsErr,bitsErr,pktsRec,stIdx,numFreqEst] = deal(0);

% Initialize data indexing variables
plFrameSize = rxParams.plFrameSize;
symSyncOutLen = zeros(rxParams.initialTimeFreqSync,1);
freqCounter = 0;
isCoarseFreqLock = false;
cCFOEstMean = [];
isFineFreqLock = false;
cCFOEst = [];
rxParams.fineFreqEstTemp = zeros(numFrames-rxParams.initialTimeSync,1);
headerDataDisplayCounter = 0;
streamFormat = "packetized";

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(rxWaveform)

    % 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(rxWaveform);
    endIdx(isLastFrame) = length(rxWaveform);
    rxData = rxWaveform(stIdx+1:endIdx);

    % After coarse frequency offset loop is converged, the FLL works with a
    % reduced loop bandwidth.
    if rxParams.frameCount < rxParams.initialTimeFreqSync
        isCoarseFreqLock = false;
    else
        isCoarseFreqLock = true;
    end

    % Retrieve the last frame samples.
    if isLastFrame
        resSymb = plFrameSize - length(rxParams.cfBuffer);
        resSampCnt = resSymb*rxParams.sps - length(rxData);
        if resSampCnt >= 0                                    % Inadequate number of samples to fill last frame
            syncIn = [rxData;zeros(resSampCnt,1)];
        else                                                  % Excess samples are available to fill last frame
            syncIn = rxData(1:resSymb*rxParams.sps);
        end
    else
        syncIn = rxData;
    end

    % Apply DC offset compensation, AGC, matched filtering, symbol timing synchronization, frame
    % synchronization, and coarse frequency offset compensation.
    syncIn = dcBlock(syncIn);
    syncIn = agc(syncIn)/sps;
    if rxParams.frameCount > 1
        [coarseFreqSyncOut,syncIndex,phEst] = timeFreqSync(syncIn,isCoarseFreqLock);
        coarseCFOEst = diff(phEst(1:sps:end)/(2*pi));
        if rxParams.frameCount <= rxParams.initialTimeSync
            symSyncOutLen = [symSyncOutLen;length(coarseFreqSyncOut)]; %#ok<*AGROW>
            if any(abs(diff(symSyncOutLen(1:rxParams.frameCount))) > 5)
                error(["Symbol timing synchronization failed. The loop will not " ...
                    "converge, resulting in frame recovery. Decrease the symbSyncLoopBW " ...
                    "parameter for proper loop convergence."]);
            end
        end
        if rxParams.frameCount > rxParams.initialTimeSync + 1
            cCFOEstMean = [cCFOEstMean;mean(coarseCFOEst)];
            cCFOEst = [cCFOEst;coarseCFOEst];
            if length(cCFOEstMean) > 2
                diffVal = diff(abs(cCFOEstMean));
                if all(diffVal(end-1:end) < 0.01) && ~isCoarseFreqLock
                    isCoarseFreqLock = true;
                    rxParams.initialTimeFreqSync = rxParams.frameCount;
                elseif isLastFrame && ~isCoarseFreqLock
                    fprintf("%s\n",["Coarse frequency error estimation failed. Try analyzing the cCFOEst " ...
                        "across frames and check carrier synchronization has converged. Try reducing the " ...
                        "carrSyncLoopBW parameters"]);
                end
            end
        end
        rxParams.syncIndex = syncIndex;
        % The PL frame start index lies somewhere in the middle of the frame being processed.
        % From fine frequency estimation, the processing happens as a PL frame.
        % A buffer stores the symbols required to fill one PL frame.
        if isLastFrame
            fineFreqIn = [rxParams.cfBuffer; coarseFreqSyncOut];
        elseif rxParams.frameCount > 1
            buffLen = rxParams.plFrameSize - length(rxParams.cfBuffer);
            if buffLen < length(coarseFreqSyncOut)
                fineFreqIn = [rxParams.cfBuffer; coarseFreqSyncOut(1:buffLen)];
            else
                fineFreqIn = [rxParams.cfBuffer; coarseFreqSyncOut];
            end
        end
        % Estimate the fine frequency error by using the HelperDVBS2FineFreqEst
        % helper function.
        % Add 1 to the conditional check because the buffer used to get one PL
        % frame introduces a delay of one to the loop count.
        if (rxParams.frameCount > rxParams.initialTimeFreqSync + 1) && ...
                ~isFineFreqLock
            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));
            rxParams.fineFreqEstTemp(1:end-1) = rxParams.fineFreqEstTemp(2:end);
            rxParams.fineFreqEstTemp(end) = freqEst;
            numFreqEst = numFreqEst + 1;
            if numFreqEst >= 5
                cg = abs(diff(rxParams.fineFreqEstTemp));
                if all(cg(end-2:end) < 1e-4)
                    isFineFreqLock = true;
                    rxParams.totalSyncFrames = rxParams.frameCount;
fprintf("Estimated carrier frequency offset in Hz = %f\n",(coarseCFOEst(end) + freqEst).*Rsym);
                elseif isLastFrame && ~isFineFreqLock
                    fprintf("%s\n","Fine frequency error estimation failed. Try analyzing the pilot fields in the PL frame to debug the issue.")
                end
            end
        end
        if isFineFreqLock
            % 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));

            % 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,rxParams.prevPhaseEst] = HelperDVBS2PhaseEst( ...
                fineFreqOut,rxParams.refPilots,rxParams.prevPhaseEst,rxParams.pilotInd);

            % Compensate for the residual frequency and phase offset by using
            % the HelperDVBS2PhaseCompensate helper function.
            if rxParams.frameCount >= rxParams.totalSyncFrames + 2
                phaseCompOut = HelperDVBS2PhaseCompensate(rxParams.ffBuffer, ...
                    rxParams.pilotEst,rxParams.pilotInd,phEstRes(2));
            end

            rxParams.ffBuffer = fineFreqOut;
            rxParams.pilotEst = phEstRes;

            % Perform phase compensation on the data portion by
            % interpolating the phase estimates computed on consecutive pilot
            % blocks. The second phase estimate is not available for the data
            % portion after the last pilot block in the last frame. Therefore,
            % the slope of phase estimates computed on all pilot blocks in the
            % last frame is extrapolated and used to compensate for the phase
            % error on the final data portion.
            if isLastFrame
                pilotBlkLen = 36;                                               % Symbols
                pilotBlkFreq = 1476;                                            % Symbols
                avgSlope = mean(diff(phEstRes(2:end)));
                chunkLen = rxParams.plFrameSize - rxParams.pilotInd(end) + ...
                    rxParams.pilotInd(pilotBlkLen);
                estEndPh = phEstRes(end) + avgSlope*chunkLen/pilotBlkFreq;
                phaseCompOut1 = HelperDVBS2PhaseCompensate(rxParams.ffBuffer, ...
                    rxParams.pilotEst,rxParams.pilotInd,estEndPh);
            end
        end

        % Recover the input bit stream.
        if rxParams.frameCount >= rxParams.totalSyncFrames + 2
            isValid = true;
            if isLastFrame
                syncOut = [phaseCompOut; phaseCompOut1];
            else
                syncOut = phaseCompOut;
            end
        else
            isValid = false;
            syncOut = [];
        end

        % Update the buffers and counters.
        rxParams.cfBuffer = coarseFreqSyncOut(rxParams.syncIndex:end);

        if isValid  % Data valid signal

            % Decode the PL header by using the dvbsPLHeaderRecover
            % function
            syncOut = syncOut/sqrt(mean(abs(syncOut).^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);
                % Synchronized data constellation plot
syncConst(rxFrame)
                % 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
                [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
    end
    stIdx = endIdx;
    rxParams.frameCount = rxParams.frameCount + 1;
end
Estimated carrier frequency offset in Hz = 1772.097899
Physical layer header detection summary
detPLParams=1×4 table
    "16APSK"    "2/3"    "normal"    "true"

PL frame number = 15
Estimated SNR in dB = 12.905461
BB header decoding passed
Total number of frames lost = 0
PL frame number = 16
Estimated SNR in dB = 13.008344
BB header decoding passed
Total number of frames lost = 0
PL frame number = 17
Estimated SNR in dB = 12.509743
BB header decoding passed
Total number of frames lost = 0
PL frame number = 18
Estimated SNR in dB = 12.698449
BB header decoding passed
Total number of frames lost = 0
PL frame number = 19
Estimated SNR in dB = 12.478942
BB header decoding passed
Total number of frames lost = 0
PL frame number = 20
Estimated SNR in dB = 12.467469
BB header decoding passed
Total number of frames lost = 0
PL frame number = 21
Estimated SNR in dB = 12.203213
BB header decoding passed
Total number of frames lost = 0
PL frame number = 22
Estimated SNR in dB = 12.799633
BB header decoding passed
Total number of frames lost = 0
PL frame number = 23
Estimated SNR in dB = 12.367894
BB header decoding passed
Total number of frames lost = 0
PL frame number = 24
Estimated SNR in dB = 12.763959
BB header decoding passed
Total number of frames lost = 0
PL frame number = 25
Estimated SNR in dB = 12.355102
BB header decoding passed
Total number of frames lost = 0
PL frame number = 26
Estimated SNR in dB = 13.135598
BB header decoding passed
Total number of frames lost = 0
PL frame number = 27
Estimated SNR in dB = 12.723067
BB header decoding passed
Total number of frames lost = 0
PL frame number = 28
Estimated SNR in dB = 13.030082
BB header decoding passed
Total number of frames lost = 0
PL frame number = 29
Estimated SNR in dB = 12.416891
BB header decoding passed
Total number of frames lost = 0
PL frame number = 30
Estimated SNR in dB = 13.409706
BB header decoding passed
Total number of frames lost = 0
PL frame number = 31
Estimated SNR in dB = 12.746534
BB header decoding passed
Total number of frames lost = 0
PL frame number = 32
Estimated SNR in dB = 12.179928
BB header decoding passed
Total number of frames lost = 0
PL frame number = 33
Estimated SNR in dB = 13.038020
BB header decoding passed
Total number of frames lost = 0
PL frame number = 34
Estimated SNR in dB = 12.640759
BB header decoding passed
Total number of frames lost = 0
PL frame number = 35
Estimated SNR in dB = 13.542063
BB header decoding passed
Total number of frames lost = 0
PL frame number = 36
Estimated SNR in dB = 12.794870
BB header decoding passed
Total number of frames lost = 0
PL frame number = 37
Estimated SNR in dB = 13.091238
BB header decoding passed
Total number of frames lost = 0
PL frame number = 38
Estimated SNR in dB = 12.852279
BB header decoding passed
Total number of frames lost = 0
PL frame number = 39
Estimated SNR in dB = 12.838353
BB header decoding passed
Total number of frames lost = 0
PL frame number = 40
Estimated SNR in dB = 13.100813
BB header decoding passed
Total number of frames lost = 0
PL frame number = 41
Estimated SNR in dB = 12.727261
BB header decoding passed
Total number of frames lost = 0
PL frame number = 42
Estimated SNR in dB = 13.153455
BB header decoding passed
Total number of frames lost = 0
PL frame number = 43
Estimated SNR in dB = 13.457814
BB header decoding passed
Total number of frames lost = 0
PL frame number = 44
Estimated SNR in dB = 13.545653
BB header decoding passed
Total number of frames lost = 0
PL frame number = 45
Estimated SNR in dB = 12.983854
BB header decoding passed
Total number of frames lost = 0
PL frame number = 46
Estimated SNR in dB = 12.866556
BB header decoding passed
Total number of frames lost = 0
PL frame number = 47
Estimated SNR in dB = 12.834604
BB header decoding passed
Total number of frames lost = 0

PL frame number = 48
Estimated SNR in dB = 12.783392
BB header decoding passed
Total number of frames lost = 0

Visualization and Error Logs

Plot the constellation of the synchronized data and compute PER.

% 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

Instrument Connection Troubleshooting

Further Exploration

  • 5G NR Waveform Acquisition and Analysis (5G Toolbox) example - Generate a 5G NR-TM waveform using the 5G Waveform Generator app, download and transmit the waveform onto a Keysight vector signal generator, and then receive the waveform using a Keysight signal analyzer for waveform analysis in MATLAB.

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

Supporting Files

The example uses these helper functions and data file:

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

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

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