Transmit and Receive LTE MIMO Using Analog Devices AD9361/AD9364

This example shows how to use the Communications Toolbox™ Support Package for Xilinx® Zynq-Based Radio Support Package with MATLAB® and LTE Toolbox™ to generate a multi-antenna LTE transmission for simultaneous transmit and receive on a single SDR platform. An image file is encoded and packed into a radio frame for transmission, and subsequently decoded on reception. The following illustration is a conceptual overview of this setup:

Refer to the Guided Host-Radio Hardware Setup documentation for details on configuring your host computer to work with the Support Package for Xilinx® Zynq-Based Radio.

Introduction

You can use the LTE Toolbox to generate standard-compliant baseband IQ downlink and uplink reference measurement channel (RMC) waveforms and downlink test model (E-TM) waveforms. These baseband waveforms can be modulated for RF transmission using SDR hardware such as Xilinx Zynq-based radio.

This example imports an image file and packs it into multiple radio frames of a baseband RMC waveform generated by using the LTE Toolbox. The example creates a continuous RF LTE waveform by using the Repeated Waveform Transmitter functionality with the Zynq radio hardware. The baseband RMC waveform is transferred to the hardware memory on the Zynq radio and transmitted continuously over the air without gaps. If you use an SDR device that is capable of multiple channel transmission and reception, the example can generate and transmit a multi-antenna LTE waveform using LTE Transmit Diversity. For an overview of devices with multiple channel support, see Channel I/O.

The example captures the resultant waveform by using the same Zynq radio hardware platform. If you have the appropriate hardware, the example can use multi-channel reception in the receiver.

Example Setup

Before you run this example, perform the following steps:

  1. Configure your host computer to work with the Xilinx Zynq-Based radio support package. See Guided Host-Radio Hardware Setup.

  2. Before running the example, make sure that LTE Toolbox is installed. The example returns an error if you do not have LTE Toolbox installed. You must have an LTE Toolbox license to run this example.

  3. You can use this example with an AD936x or an FMCOMMS5 radio hardware. By default, the example is configured to run with AD936x. To configure the example for FMCOMMS5, you must use the comm.SDRTxFMCOMMS5 and comm.SDRRxFMCOMMS5 objects instead of the comm.SDRTxAD936x and comm.SDRRxAD936x objects. To update the example for FMCOMMS5, follow the instructions in the inline comments.

Check that LTE Toolbox is installed, and that there is a valid license

if isempty(ver('lte')) % Check for LST install
    error('zynqRadioLTEMIMOTransmitReceive:NoLST', ...
        'Please install LTE Toolbox to run this example.');
elseif ~license('test', 'LTE_Toolbox') % Check that a valid license is present
    error('zynqRadioLTEMIMOTransmitReceive:NoLST', ...
        'A valid license for LTE Toolbox is required to run this example.');
end

The example configures all scopes and figures displayed throughout the example.

% Setup handle for image plot
if ~exist('imFig', 'var') || ~ishandle(imFig)
    imFig = figure;
    imFig.NumberTitle = 'off';
    imFig.Name = 'Image Plot';
    imFig.Visible = 'off';
else
    clf(imFig); % Clear figure
    imFig.Visible = 'off';
end

% Setup handle for channel estimate plots
if ~exist('hhest', 'var') || ~ishandle(hhest)
    hhest = figure('Visible','Off');
    hhest.NumberTitle = 'off';
    hhest.Name = 'Channel Estimate';
else
    clf(hhest); % Clear figure
    hhest.Visible = 'off';
end

% Setup Spectrum viewer
spectrumScope = dsp.SpectrumAnalyzer( ...
    'SpectrumType',    'Power density', ...
    'SpectralAverages', 10, ...
    'YLimits',         [-130 -40], ...
    'Title',           'Received Baseband LTE Signal Spectrum', ...
    'YLabel',          'Power spectral density');

% Setup the constellation diagram viewer for equalized PDSCH symbols
constellation = comm.ConstellationDiagram('Title','Equalized PDSCH Symbols',...
                                'ShowReferenceConstellation',false);

By default, the example uses an AD936x device with two channels. If you are using an FMCOMMS5 RF card, set txsim.SDRDeviceName to 'FMCOMMS5' instead of 'AD936x'. This setting also enables the use of four channels later on.

%  Initialize SDR device
txsim = struct; % Create empty structure for transmitter
txsim.SDRDeviceName = 'AD936x'; % Set SDR Device
% To update the example for FMCOMMS5, set |txsim.SDRDeviceName| to
% |'FMCOMMS5'|.
radio = sdrdev(txsim.SDRDeviceName); % Create SDR device object

Run Example

You can run this example by executing zynqRadioLTEMIMOTransmitReceiveAD9361AD9364ML. The following sections explain the design and architecture of this example, and what you can expect to see as the code is executed.

Transmitter Design: System Architecture

The general structure of the LTE transmitter consists of these steps:

  1. Import and convert an image to a binary data stream.

  2. Generate a baseband LTE signal using LTE Toolbox, packing the binary data stream into the transport blocks of the downlink shared channel (DL-SCH).

  3. Prepare the baseband signal for transmission using the SDR hardware.

  4. Send the baseband data to the SDR hardware for upsampling and continuous transmission at the desired center frequency.

Set Up SDR Transmitter

The txsim structure controls the properties of the SDR transmitter System object. By default, the example uses an AD936x device with two channels. If you are using an FMCOMMS4 RF card with your device, you have only one channel. Set txsim.NTxAnts to 1.

If you have set txsim.SDRDeviceName to 'FMCOMMS5' in the previous section, the example automatically chooses four channels.

txsim.RC = 'R.7';       % Base RMC configuration, 10 MHz bandwidth
txsim.NCellID = 88;     % Cell identity
txsim.NFrame = 700;     % Initial frame number
txsim.TotFrames = 1;    % Number of frames to generate
txsim.DesiredCenterFrequency = 2.45e9; % Center frequency in Hz
switch txsim.SDRDeviceName
    case 'AD936x'
        txsim.NTxAnts = 2;      % Number of transmit antennas
%         txsim.NTxAnts = 1;
    case 'FMCOMMS5'
        txsim.NTxAnts = 4;
    otherwise
        error('Unknown SDR device: %s',txsim.SDRDeviceName);
end

% txsim.NTxAnts = 1;

To visualize the benefit of using multi-channel transmission and reception over single-channel, you can reduce the transmitter gain parameter to impair the quality of the received waveform. For example, set txsim.Gain to -20 instead of -10. Adjust this value depending on your antenna configuration.

% TX gain parameter:
txsim.Gain = -10;

Create the SDR transmitter System object with the specified properties.

sdrTransmitter = sdrtx(txsim.SDRDeviceName);

Prepare Image File

The example reads data from the image file, scales it for transmission, and converts it to a binary data stream.

The size of the transmitted image directly impacts the number of LTE radio frames required for the transmission of the image data. A scaling factor of scale = 0.5 requires five LTE radio frame transmissions. Increasing the scaling factor results in more frame transmissions; Reducing the scaling factor reduces the number of frames.

% Input an image file and convert to binary stream
fileTx = 'peppers.png';            % Image file name
fData = imread(fileTx);            % Read image data from file
scale = 0.5;                       % Image scaling factor
origSize = size(fData);            % Original input image size
scaledSize = max(floor(scale.*origSize(1:2)),1); % Calculate new image size
heightIx = min(round(((1:scaledSize(1))-0.5)./scale+0.5),origSize(1));
widthIx = min(round(((1:scaledSize(2))-0.5)./scale+0.5),origSize(2));
fData = fData(heightIx,widthIx,:); % Resize image
imsize = size(fData);              % Store new image size
binData = dec2bin(fData(:),8);     % Convert to 8 bit unsigned binary
trData = reshape((binData-'0').',1,[]).'; % Create binary stream

The example displays the image file to be transmitted. When the image file is successfully received and decoded, the example displays received image.

% Plot transmit image
figure(imFig);
imFig.Visible = 'on';
subplot(211);
    imshow(fData);
    title('Transmitted Image');
subplot(212);
    title('Received image will appear here...');
    set(gca,'Visible','off'); % Hide axes
    set(findall(gca, 'type', 'text'), 'visible', 'on'); % Unhide title

pause(1); % Pause to plot Tx image

Generate Baseband LTE Signal

The example uses the default configuration parameters defined in TS36.101 Annex A.3 [ 1 ] add a space to generate an RMC by using lteRMCDL. The parameters within the configuration structure rmc can be customized as required. The example generates a baseband waveform, eNodeBOutput, a fully populated resource grid, txGrid, and the full configuration of the RMC by using the lteRMCDLTool. The example uses the binary data stream that was created from the input image file trData as input to the transport coding, and packs it into multiple transport blocks in the physical downlink shared channel (PDSCH). The number of frames that are generated for transmission depends on the image scaling set when importing the image file.

% Create RMC
rmc = lteRMCDL(txsim.RC);

% Calculate the required number of LTE frames based on the size of the
% image data
trBlkSize = rmc.PDSCH.TrBlkSizes;
txsim.TotFrames = ceil(numel(trData)/sum(trBlkSize(:)));

% Customize RMC parameters
rmc.NCellID = txsim.NCellID;
rmc.NFrame = txsim.NFrame;
rmc.TotSubframes = txsim.TotFrames*10; % 10 subframes per frame
rmc.CellRefP = txsim.NTxAnts; % Configure number of cell reference ports
rmc.PDSCH.RVSeq = 0;

% Fill subframe 5 with dummy data
rmc.OCNGPDSCHEnable = 'On';
rmc.OCNGPDCCHEnable = 'On';

% If transmitting over two channels enable transmit diversity
if rmc.CellRefP >= 2
    rmc.PDSCH.TxScheme = 'TxDiversity';
    rmc.PDSCH.NLayers = txsim.NTxAnts;
    rmc.OCNGPDSCH.TxScheme = 'TxDiversity';
end

fprintf('\nGenerating LTE transmit waveform:\n')
fprintf('  Packing image data into %d frame(s).\n\n', txsim.TotFrames);

% Pack the image data into a single LTE frame
[eNodeBOutput,txGrid,rmc] = lteRMCDLTool(rmc,trData);
Generating LTE transmit waveform:
  Packing image data into 5 frame(s).

Prepare for Transmission

The transmitter uses the transmitRepeat functionality to continuously transmit the baseband LTE waveform in a loop from the DDR memory on the Zynq-based radio platform. The example displays the applied channel mapping of the transmitter based on the number of antennas.

sdrTransmitter.BasebandSampleRate = rmc.SamplingRate; % 15.36 Msps for default RMC (R.7)
                                          % with a bandwidth of 10 MHz
sdrTransmitter.CenterFrequency = txsim.DesiredCenterFrequency;
sdrTransmitter.ShowAdvancedProperties = true;
sdrTransmitter.Gain = txsim.Gain;

% Apply TX channel mapping
if txsim.NTxAnts == 2
    fprintf('Setting channel map to ''[1 2]''.\n\n');
    sdrTransmitter.ChannelMapping = [1,2];
elseif txsim.NTxAnts == 4
    fprintf('Setting channel map to ''[1 2 3 4]''.\n\n');
    sdrTransmitter.ChannelMapping = [1,2,3,4];
else
    fprintf('Setting channel map to ''1''.\n\n');
    sdrTransmitter.ChannelMapping = 1;
end

% Scale the signal for better power output.
powerScaleFactor = 0.8;
if txsim.NTxAnts >= 2
    for i =1:txsim.NTxAnts
        eNodeBOutput(:,i) = eNodeBOutput(:,i).*(1/max(abs(eNodeBOutput(:,i)))*powerScaleFactor);
    end
else
    eNodeBOutput = eNodeBOutput.*(1/max(abs(eNodeBOutput))*powerScaleFactor);
end

% Cast the transmit signal to int16 ---
% this is the native format for the SDR hardware.
eNodeBOutput = int16(eNodeBOutput*2^15);
Setting channel map to '[1 2]'.

Repeated transmission using SDR Hardware

The transmitRepeat function transfers the baseband LTE transmission to the SDR platform and stores the signal samples in the hardware memory. The example transmits the waveform continuously over the air without gaps until the transmitter System object is released. The function displays a message confirming that the transmission has started successfully.

transmitRepeat(sdrTransmitter,eNodeBOutput);
## Establishing connection to hardware. This process can take several seconds.
## Waveform transmission has started successfully and will repeat indefinitely. 
## Call the release method to stop the transmission.

Receiver Design: System Architecture

The general structure of the LTE receiver consists of these steps:

  1. Capture a suitable number of frames of the transmitted LTE signal using SDR hardware.

  2. Determine and correct the frequency offset of the received signal.

  3. Synchronize the captured signal to the start of an LTE frame.

  4. OFDM demodulate the received signal to get an LTE resource grid.

  5. Perform a channel estimation for the received signal.

  6. Decode the PDSCH and DL-SCH to obtain the transmitted data from the transport blocks of each radio frame.

  7. Recombine received transport block data to form the received image.

This example plots the power spectral density of the captured waveform, and shows visualizations of the estimated channel, equalized PDSCH symbols, and received image.

Set Up SDR Receiver

The rxsim structure controls the properties of the SDR receiver System object. The sample rate of the receiver is 15.36MHz, which is the standard sample rate for capturing an LTE bandwidth of 50 resource blocks (RBs). 50 RBs is equivalent to a signal bandwidth of 10 MHz.

% User defined parameters --- configure the same as transmitter
rxsim = struct;
rxsim.RadioFrontEndSampleRate = sdrTransmitter.BasebandSampleRate; % Configure for same sample rate
                                                       % as transmitter
rxsim.RadioCenterFrequency = txsim.DesiredCenterFrequency;
rxsim.NRxAnts = txsim.NTxAnts;
rxsim.FramesPerCapture = txsim.TotFrames+1; % Number of LTE frames to capture.
                                          % Capture 1 more LTE frame than transmitted to
                                          % allow for timing offset wraparound...
rxsim.numCaptures = 1; % Number of captures

% Derived parameters
samplesPerFrame = 10e-3*rxsim.RadioFrontEndSampleRate; % LTE frames period is 10 ms

captureTime = rxsim.FramesPerCapture * 10e-3; % LTE frames period is 10 ms

Create an SDR receiver System object with the specied properties for the device used for the image transmission.

rxsim.SDRDeviceName = txsim.SDRDeviceName;
sdrReceiver = sdrrx(rxsim.SDRDeviceName);
sdrReceiver.BasebandSampleRate = rxsim.RadioFrontEndSampleRate;
sdrReceiver.CenterFrequency = rxsim.RadioCenterFrequency;
sdrReceiver.OutputDataType = 'double';

% Configure RX channel map
sdrReceiver.ChannelMapping = 1:rxsim.NRxAnts;

Set Up LTE Receiver

The example simplifies the LTE signal reception by assuming that the transmitted PDSCH properties are known. FDD duplexing mode and a normal cyclic prefix length are also assumed as well as four cell-specific reference ports (CellRefP) for the master information block(MIB) decode. The number of actual CellRefP is provided by the MIB. For a detailed example of how to perform a blind LTE cell search and recover basic system information from an LTE waveform, see the LTE Receiver with Analog Devices™ AD9361/AD9364 example.

enb.PDSCH = rmc.PDSCH;
enb.DuplexMode = 'FDD';
enb.CyclicPrefix = 'Normal';
enb.CellRefP = 4;

The sampling rate of the signal controls the captured bandwidth. The number of RBs captured is obtained from a lookup table using the chosen sampling rate.

% Bandwidth: {1.4 MHz, 3 MHz, 5 MHz, 10 MHz, 20 MHz}
SampleRateLUT = [1.92 3.84 7.68 15.36 30.72]*1e6;
NDLRBLUT = [6 15 25 50 100];
enb.NDLRB = NDLRBLUT(SampleRateLUT==rxsim.RadioFrontEndSampleRate);
if isempty(enb.NDLRB)
    error('Sampling rate not supported. Supported rates are %s.',...
            '1.92 MHz, 3.84 MHz, 7.68 MHz, 15.36 MHz, 30.72 MHz');
end
fprintf('\nSDR hardware sampling rate configured to capture %d LTE RBs.\n',enb.NDLRB);
SDR hardware sampling rate configured to capture 50 LTE RBs.

Channel estimation is configured to be performed using cell-specific reference signals. A 9-by-9 averaging window is used to minimize the effect of noise.

% Channel estimation configuration structure
cec.PilotAverage = 'UserDefined';  % Type of pilot symbol averaging
cec.FreqWindow = 9;                % Frequency window size in REs
cec.TimeWindow = 9;                % Time window size in REs
cec.InterpType = 'Cubic';          % 2D interpolation type
cec.InterpWindow = 'Centered';     % Interpolation window type
cec.InterpWinSize = 3;             % Interpolation window size

Capture and Process Signal

The example uses a while loop to capture and decode bursts of LTE frames. As the LTE waveform is continually transmitted over the air in a loop, the first frame captured by the receiver is not guaranteed to be the first transmitted frame. This means that the frames may be decoded out of sequence. To enable the received frames to be recombined in the correct order, their frame numbers must be determined. The MIB contains information on the current system frame number, and therefore must be decoded. After the frame number has been determined, the example decodes the PDSCH and DL-SCH and displays the equalized PDSCH symbols. No data is transmitted in subframe 5; therefore the captured data for subframe is ignored for the decoding. The power spectral density (PSD) of the captured waveform is plotted to show the received LTE transmission.

When the LTE frames have been successfully decoded, the example displays the detected frame number on a frame-by-frame basis and the equalized PDSCH symbol constellation for each subframe. The example also displays an estimate of the channel magnitude frequency response between cell reference point 0 and the receive antenna for each frame.

enbDefault = enb;

while rxsim.numCaptures
    % Set default LTE parameters
    enb = enbDefault;

    % SDR Capture
    fprintf('\nStarting a new RF capture.\n\n')

    % rxWaveform holds |rxsim.FramesPerCapture| number of consecutive frames worth
    % of contiguous baseband LTE samples.
    rxWaveform = capture(sdrReceiver, captureTime, 'Seconds');

    if rxsim.NRxAnts > 1
        spectrumScope.ShowLegend = true; % Turn on legend for spectrum analyzer
        spectrumScope.ChannelNames = cellfun(@(x) ['SDR Channel ' num2str(x)], num2cell(1:4), 'UniformOutput', false);
    end

    % Show power spectral density of captured burst
    spectrumScope.SampleRate = rxsim.RadioFrontEndSampleRate;
    spectrumScope(rxWaveform);

    % Perform frequency offset correction for known cell ID
    frequencyOffset = lteFrequencyOffset(enb,rxWaveform);
    rxWaveform = lteFrequencyCorrect(enb,rxWaveform,frequencyOffset);
    fprintf('\nCorrected a frequency offset of %i Hz.\n',frequencyOffset)

    % Perform the blind cell search to obtain cell identity and timing offset
    %   Use 'PostFFT' SSS detection method to improve speed
    cellSearch.SSSDetection = 'PostFFT'; cellSearch.MaxCellCount = 1;
    [NCellID,frameOffset] = lteCellSearch(enb,rxWaveform,cellSearch);
    fprintf('Detected a cell identity of %i.\n', NCellID);
    enb.NCellID = NCellID; % From lteCellSearch

    % Sync the captured samples to the start of an LTE frame, and trim off
    % any samples that are part of an incomplete frame.
    rxWaveform = rxWaveform(frameOffset+1:end,:);
    tailSamples = mod(length(rxWaveform),samplesPerFrame);
    rxWaveform = rxWaveform(1:end-tailSamples,:);
    enb.NSubframe = 0;
    fprintf('Corrected a timing offset of %i samples.\n',frameOffset)

    % OFDM demodulation
    rxGrid = lteOFDMDemodulate(enb,rxWaveform);

    % Perform channel estimation for 4 CellRefP as currently we do not
    % know the CellRefP for the eNodeB.
    [hest,nest] = lteDLChannelEstimate(enb,cec,rxGrid);

    sfDims = lteResourceGridSize(enb);
    Lsf = sfDims(2); % OFDM symbols per subframe
    LFrame = 10*Lsf; % OFDM symbols per frame
    numFullFrames = length(rxWaveform)/samplesPerFrame;

    rxDataFrame = zeros(sum(enb.PDSCH.TrBlkSizes(:)),numFullFrames);
    recFrames = zeros(numFullFrames,1);
    rxSymbols = []; txSymbols = [];

    % For each frame decode the MIB, PDSCH and DL-SCH
    for frame = 0:(numFullFrames-1)
        fprintf('\nPerforming DL-SCH Decode for frame %i of %i in burst:\n', ...
            frame+1,numFullFrames)

        % Extract subframe #0 from each frame of the received resource grid
        % and channel estimate.
        enb.NSubframe = 0;
        rxsf = rxGrid(:,frame*LFrame+(1:Lsf),:);
        hestsf = hest(:,frame*LFrame+(1:Lsf),:,:);

        % PBCH demodulation. Extract resource elements (REs)
        % corresponding to the PBCH from the received grid and channel
        % estimate grid for demodulation.
        enb.CellRefP = 4;
        pbchIndices = ltePBCHIndices(enb);
        [pbchRx,pbchHest] = lteExtractResources(pbchIndices,rxsf,hestsf);
        [~,~,nfmod4,mib,CellRefP] = ltePBCHDecode(enb,pbchRx,pbchHest,nest);

        % If PBCH decoding successful CellRefP~=0 then update info
        if ~CellRefP
            fprintf('  No PBCH detected for frame.\n');
            continue;
        end
        enb.CellRefP = CellRefP; % From ltePBCHDecode

        % Decode the MIB to get current frame number
        enb = lteMIB(mib,enb);

        % Incorporate the nfmod4 value output from the function
        % ltePBCHDecode, as the NFrame value established from the MIB
        % is the system frame number modulo 4.
        enb.NFrame = enb.NFrame+nfmod4;
        fprintf('  Successful MIB Decode.\n')
        fprintf('  Frame number: %d.\n',enb.NFrame);

        % The eNodeB transmission bandwidth may be greater than the
        % captured bandwidth, so limit the bandwidth for processing
        enb.NDLRB = min(enbDefault.NDLRB,enb.NDLRB);

        % Store received frame number
        recFrames(frame+1) = enb.NFrame;

        % Process subframes within frame (ignoring subframe 5)
        for sf = 0:9
            if sf~=5 % Ignore subframe 5
                % Extract subframe
                enb.NSubframe = sf;
                rxsf = rxGrid(:,frame*LFrame+sf*Lsf+(1:Lsf),:);

                % Perform channel estimation with the correct number of CellRefP
                [hestsf,nestsf] = lteDLChannelEstimate(enb,cec,rxsf);

                % PCFICH demodulation. Extract REs corresponding to the PCFICH
                % from the received grid and channel estimate for demodulation.
                pcfichIndices = ltePCFICHIndices(enb);
                [pcfichRx,pcfichHest] = lteExtractResources(pcfichIndices,rxsf,hestsf);
                [cfiBits,recsym] = ltePCFICHDecode(enb,pcfichRx,pcfichHest,nestsf);

                % CFI decoding
                enb.CFI = lteCFIDecode(cfiBits);

                % Get PDSCH indices
                [pdschIndices,pdschIndicesInfo] = ltePDSCHIndices(enb, enb.PDSCH, enb.PDSCH.PRBSet);
                [pdschRx, pdschHest] = lteExtractResources(pdschIndices, rxsf, hestsf);

                % Perform deprecoding, layer demapping, demodulation and
                % descrambling on the received data using the estimate of
                % the channel
                [rxEncodedBits, rxEncodedSymb] = ltePDSCHDecode(enb,enb.PDSCH,pdschRx,...
                                               pdschHest,nestsf);

                % Append decoded symbol to stream
                rxSymbols = [rxSymbols; rxEncodedSymb{:}]; %#ok<AGROW>

                % Transport block sizes
                outLen = enb.PDSCH.TrBlkSizes(enb.NSubframe+1);

                % Decode DownLink Shared Channel (DL-SCH)
                [decbits{sf+1}, blkcrc(sf+1)] = lteDLSCHDecode(enb,enb.PDSCH,...
                                                outLen, rxEncodedBits);  %#ok<SAGROW>

                % Recode transmitted PDSCH symbols for EVM calculation
                %   Encode transmitted DLSCH
                txRecode = lteDLSCH(enb,enb.PDSCH,pdschIndicesInfo.G,decbits{sf+1});
                %   Modulate transmitted PDSCH
                txRemod = ltePDSCH(enb, enb.PDSCH, txRecode);
                %   Decode transmitted PDSCH
                [~,refSymbols] = ltePDSCHDecode(enb, enb.PDSCH, txRemod);
                %   Add encoded symbol to stream
                txSymbols = [txSymbols; refSymbols{:}]; %#ok<AGROW>

                release(constellation); % Release previous constellation plot
                constellation(rxEncodedSymb{:}); % Plot current constellation
                pause(0); % Allow constellation to repaint
            end
        end

        % Reassemble decoded bits
        fprintf('  Retrieving decoded transport block data.\n');
        rxdata = [];
        for i = 1:length(decbits)
            if i~=6 % Ignore subframe 5
                rxdata = [rxdata; decbits{i}{:}]; %#ok<AGROW>
            end
        end

        % Store data from receive frame
        rxDataFrame(:,frame+1) = rxdata;

        % Plot channel estimate between CellRefP 0 and the receive antennae
        focalFrameIdx = frame*LFrame+(1:LFrame);
        figure(hhest);
        hhest.Visible = 'On';
        surf(abs(hest(:,focalFrameIdx,1,1)));
        shading flat;
        xlabel('OFDM symbol index');
        ylabel('Subcarrier index');
        zlabel('Magnitude');
        title('Estimate of Channel Magnitude Frequency Repsonse');
    end
    rxsim.numCaptures = rxsim.numCaptures-1;
end
% Release both the transmitter and receiver objects once reception is complete
release(sdrTransmitter);
release(sdrReceiver);
Starting a new RF capture.

## Establishing connection to hardware. This process can take several seconds.

Corrected a frequency offset of -6.552114e-01 Hz.
Detected a cell identity of 88.
Corrected a timing offset of 9264 samples.

Performing DL-SCH Decode for frame 1 of 5 in burst:
  Successful MIB Decode.
  Frame number: 701.
  Retrieving decoded transport block data.

Performing DL-SCH Decode for frame 2 of 5 in burst:
  Successful MIB Decode.
  Frame number: 702.
  Retrieving decoded transport block data.

Performing DL-SCH Decode for frame 3 of 5 in burst:
  Successful MIB Decode.
  Frame number: 703.
  Retrieving decoded transport block data.

Performing DL-SCH Decode for frame 4 of 5 in burst:
  Successful MIB Decode.
  Frame number: 704.
  Retrieving decoded transport block data.

Performing DL-SCH Decode for frame 5 of 5 in burst:
  Successful MIB Decode.
  Frame number: 700.
  Retrieving decoded transport block data.

Result Qualification and Display

To determine the quality of the received data, the example calculates the bit error rate(BER) between the transmitted and received data. The received data is then reformed into an image and displayed.

% Determine index of first transmitted frame (lowest received frame number)
[~,frameIdx] = min(recFrames);

fprintf('\nRecombining received data blocks:\n');

decodedRxDataStream = zeros(length(rxDataFrame(:)),1);
frameLen = size(rxDataFrame,1);
% Recombine received data blocks (in correct order) into continuous stream
for n=1:numFullFrames
    currFrame = mod(frameIdx-1,numFullFrames)+1; % Get current frame index
    decodedRxDataStream((n-1)*frameLen+1:n*frameLen) = rxDataFrame(:,currFrame);
    frameIdx = frameIdx+1; % Increment frame index
end

% Perform EVM calculation
if ~isempty(rxSymbols)
    evmCalculator = comm.EVM();
    evmCalculator.MaximumEVMOutputPort = true;
    [evm.RMS,evm.Peak] = evmCalculator(txSymbols, rxSymbols);
    fprintf('  EVM peak = %0.3f%%\n',evm.Peak);
    fprintf('  EVM RMS  = %0.3f%%\n',evm.RMS);
else
    fprintf('  No transport blocks decoded.\n');
end

% Perform bit error rate (BER) calculation
bitErrorRate = comm.ErrorRate;
err = bitErrorRate(decodedRxDataStream(1:length(trData)), trData);
fprintf('  Bit Error Rate (BER) = %0.5f.\n', err(1));
fprintf('  Number of bit errors = %d.\n', err(2));
fprintf('  Number of transmitted bits = %d.\n',length(trData));

% Recreate image from received data
fprintf('\nConstructing image from received data.\n');
str = reshape(sprintf('%d',decodedRxDataStream(1:length(trData))), 8, []).';
decdata = uint8(bin2dec(str));
receivedImage = reshape(decdata,imsize);

% Plot receive image
if exist('imFig', 'var') && ishandle(imFig) % If TX figure is open
    figure(imFig); subplot(212);
else
    figure; subplot(212);
end
imshow(receivedImage);
title(sprintf('Received Image: %dx%d Antenna Configuration',txsim.NTxAnts, rxsim.NRxAnts));
Recombining received data blocks:
  EVM peak = 5.279%
  EVM RMS  = 0.726%
  Bit Error Rate (BER) = 0.00000.
  Number of bit errors = 0.
  Number of transmitted bits = 1179648.

Constructing image from received data.

Things to Try

By default, the example uses two antennas for transmission and reception of the LTE waveform. Depending on your hardware, you can modify the SDR transmitter and receiver to use a single or four antennas. To observe the difference in the EVM and BER after signal reception and processing, you can decrease the transmitter gain. Check for any errors in the displayed received image.

Troubleshooting the Example

For more information on troubleshooting SDR hardware and the Communications Toolbox Support Package for Xilinx Zynq-Based Radio, see Common Problems and Fixes.

Selected Bibliography

  1. 3GPP TS 36.191. "User Equipment (UE) radio transmission and reception." 3rd Generation Partnership Project; Technical Specification Group Radio Access Network; Evolved Universal Terrestrial Radio Access (E-UTRA).