%% LTE-M Downlink Waveform Generation 
% This example shows how to create a downlink LTE-M transmission consisting
% of MTC Physical Downlink Control Channel (MPDCCH) as well as its
% associated Physical Downlink Shared Channel (PDSCH) and Physical
% Broadcast Channel (PBCH), including repetitions and frequency hopping.
% When compared to pre-Release 13 devices, Cat-M devices offer lower cost
% and complexity, enhanced coverage by the introduction of repetitions and
% an extended DRX for further power saving.

% Copyright 2017-2019 The MathWorks, Inc.

%% Introduction 
% The introduction of LTE-M to the LTE standard added support specifically
% aimed at Machine-Type Communications (MTC). Starting with Cat-0 
% devices in Release 12, this was further extended in later releases to
% define a separate Cat-M class of devices. Two categories have now been
% added to LTE, Cat-M1 in Release 13 (through the _eMTC_ work items)
% followed by Cat-M2 in Release 14 ( _feMTC_ ).
%
% There are two coverage enhancement (CE) modes of operation for Cat-M
% devices (also referred to as BL/CE UEs in 3GPP standard documents), CE
% mode A and CE mode B. The CE mode A targets modest coverage enhancement
% with up to 32 repetitions whereas CE mode B targets extensive coverage
% enhancement with up to 2048 repetitions for the data channel. CE mode A
% is signaled via DCI format 6-0A/6-1A messages and CE mode B via 6-0B/6-1B
% messages. The MPDCCH processing chain, DM-RS creation and mapping is
% almost identical to that of the Enhanced Physical Downlink Control
% Channel (EPDCCH), plus the addition of repetitions and frequency hopping
% behavior. This example makes specific use of LTE Toolbox(TM)'s EPDCCH
% functionality to implement the MPDCCH model. The LTE-M data channel is
% the LTE PDSCH with addition of repetitions and frequency hopping. The
% LTE-M broadcast channel consists of two parts; the 'core' part
% corresponding to the LTE PBCH and the LTE-M specific 'repetition' part
% where the symbols and cell RS signals in the 'core' part are repeated.
%
% LTE-M can be deployed in standard LTE cells, therefore not all subframes
% are necessarily used for BL/CE transmission. The BL/CE subframes are
% indicated by a bitmap sent in the MIB-M message (similar to the mechanism
% in NB-IoT). For simplicity, in this example, we assume that all subframes
% are defined to be BL/CE. The MPDCCH/PDSCH starting OFDM symbol for LTE-M
% transmissions are cell-specific and is broadcasted in the System
% Information (SI).
%
% The main output of this MATLAB(R) example is a multi-subframe
% Cat-M1/Cat-M2 resource grid containing the MPDCCH Resource Elements (RE),
% associated DM-RS, the LTE-M PDSCH REs, PBCH REs (both 'core' and
% 'repetition' parts along with corresponding cell reference signals) and
% other reference signals as configured for the full transmission sequence.
% This grid is also OFDM modulated to generate the associated time-domain
% baseband waveform. Plots are created to provide visualization of the RE
% assignment in the grid and of the magnitude of the baseband signal.

%% LTE-M Physical Layer Concepts
% * _Repetitions -_ To enable significantly extended coverage for LTE-M
% devices, repetitions for MPDCCH, PDSCH and PBCH were introduced for Cat-M
% devices in Release 13. This would provide at least 15dB performance
% improvement over pre-release 13 devices. MPDCCH can be repeated up to a
% maximum of 256 times, PDSCH up to 2048 and PBCH up to 5 including the
% 'core' part.
% 
% * _Narrowbands -_ LTE-M uses the concept of narrowbands to allocate
% subcarriers in the wideband LTE carrier for data and control channels.
% Each narrowband consists of 6 consecutive PRBs but not all PRBs are
% necessarily part of the narrowbands (dependent on the overall carrier
% BW).
% 
% * _Widebands -_ Release 14 LTE-M uses the concept of widebands to
% allocate higher bandwidth for the data channel. There can be one or more
% widebands, each consisting of 4 narrowbands or a single wideband
% consisting of 1,2 or 3 narrowbands. For a Cat-M2 device configured in CE
% mode A (DCI format 6-1A), the data channel is transmitted on a single
% wideband if |ce-pdsch-maxBandwidth-config| is set to 5MHz or |resource
% block assignment flag| is set to 1 or across the full LTE carrier
% bandwidth via an RBG bitmap in the case of |resource block assignment
% flag| is set to 0. The |resource block assignment flag| is only present
% if the |ce-pdsch-maxBandwidth-config| is set to 20MHz. For a Cat-M2
% device configured in CE mode B (DCI format 6-1B), the data channel is
% transmitted on a single wideband if |ce-pdsch-maxBandwidth-config| is set
% to 5MHz and up to 4 widebands if |ce-pdsch-maxBandwidth-config| is set to
% 20MHz.
% 
% * _Frequency Hopping -_ Although a Release 13 eMTC device has an
% instantaneous bandwidth of 1.4MHz (the simplest LTE-M devices have a
% maximum bandwidth of 1.4MHz), it can access a wider LTE carrier through
% different narrowbands between the subframes. If the transmission involves
% repetition over multiple subframes, optional inter-subframe frequency
% hopping can be applied. The frequency hopping happens between different
% narrowbands and in blocks of 1 to 16 subframes depending on CE mode. The
% hopping block length and hopping offset are cell-specific parameters. In
% the downlink, for both control and data, the frequency hopping can be
% over 2 narrowbands or 4 equally spaced narrowbands.

%% PDSCH Physical Layer Processing and Procedures
% LTE-M data transmission uses the same physical channel (PDSCH) as in the
% case of LTE. The difference however is that LTE-M enables optional
% repetitions and frequency hopping.
% 
% * _Transmission modes -_ The valid transmission modes for PDSCH for LTE-M
% are 1 (single antenna), 2 (transmit diversity), 6 (closed loop codebook
% based precoding) and 9 (non-codebook based precoding, single layer).
% Transmission mode 6 is only supported in CE mode A, whereas 1, 2 and 9
% are supported in both CE mode A and CE mode B. Unlike LTE PDSCH, multiple
% input multiple output (MIMO) operation is not supported in LTE-M because
% most LTE-M devices are expected to be low cost devices with a single
% receive antenna.
% 
% * _Repetitions and scrambling blocks -_ The PDSCH is transmitted in
% |NRepPDSCH| (>=1) consecutive BL/CE downlink subframes. These |NRepPDSCH|
% subframes are transmitted in blocks of |Nacc| subframes (see TS 36.211
% section 6.8B.2 [ <#23 1> ]) and the same scrambling sequence is applied
% to all subframes in the block. |Nacc| can be 1 or 4 in FDD duplex mode
% and 1 or 10 in TDD duplex mode. There can be up to 32 repetitions in CE
% mode A and up to 2048 repetitions in CE mode B. The number of PDSCH
% repetitions is defined by a combination of semi-static configuration and
% dynamic selection for a particular transmission.
% 
% * _Narrowbands and Widebands -_ The PRBs used for LTE-M PDSCH
% transmissions must belong to narrowband(s) (and wideband(s) if Cat-M2).
% Cat-M1 devices have an instantaneous transmission bandwidth of 1.4MHz in
% a narrowband. Cat-M2 devices have a bandwidth of 5MHz or 20MHz as
% indicated by the higher layer parameter |ce-pdsch-maxBandwidth-config|,
% in this case the PDSCH transmission can be in wideband(s) where each
% wideband consists of up to 4 non-overlapping narrowbands.
% 
% * _Frequency Hopping -_ If the PDSCH is repeated over multiple subframes,
% inter-subframe frequency hopping can be optionally applied where the
% hopping occurs for blocks of subframes of length 1,2,4,8 for devices in
% CE mode A and 2,4,8,16 in CE mode B. The hopping block length and hopping
% offset are cell-specific parameters. The frequency hopping can be over 2
% narrowbands or 4 equally spaced narrowbands. The relative positions of
% the RBs carrying the PDSCH within each hopping narrowbands remains the
% same.

%% MPDCCH Physical Layer Processing and Procedures
% MPDCCH carries the LTE-M downlink control information (DCI). The MPDCCH
% and corresponding Demodulation Reference Signals (DM-RS) are transmitted
% on one or more ports from the set (107,108,109,110). The physical layer
% processing stages and operations of the MPDCCH and EPDCCH are very
% similar, with the differences being the repetitions, optional frequency
% hopping and how the scrambling is applied.
%
% * _Repetitions and scrambling blocks -_ The MPDCCH is transmitted using
% an aggregation of one or more consecutive Enhanced Control Channel
% Elements (ECCEs) in |NRepMPDCCH| (>=1) consecutive BL/CE downlink
% subframes. These |NRepMPDCCH| subframes are transmitted in blocks of
% |Nacc| subframes (see TS 36.211 section 6.8B.2 [ <#23 1> ]) and the same
% scrambling sequence is applied to all subframes in the block. As an
% example, for MPDCCH not associated with P-RNTI or SC-RNTI and configured
% with CE mode A, |Nacc| = 1 as described in TS 36.211 section 6.8B.2 [
% <#23 1> ] so the scrambling gets initialized every BL/CE subframe, as in
% the case of EPDCCH. |Nacc| can be 1 or 4 in FDD duplex mode and 1 or 10
% in TDD duplex mode. The number of MPDCCH repetitions is defined by a
% combination of semi-static configuration and dynamic selection for a
% particular transmission. The network semi-statically configures the
% maximum repetitions |Rmax| from the set (1,2,4,8,16,32,64,128,256) then
% dynamically selects the actual repetitions for a specific transmission
% from the set (Rmax, Rmax/2, Rmax/4, Rmax/8).
% 
% * _Narrowbands -_ The MPDCCH is transmitted in 2, 4 or 6 RBs in a single
% narrowband within each subframe. MPDCCH PRB set consists of ECCEs
% numbered from 0...N'ECCEpk where N'ECCEpk is the number of ECCEs in
% MPDCCH-PRB-set p of subframe k. The number of ECCEs used for one MPDCCH
% is given by TS 36.211 Table 6.8A.1-2 [ <#23 1> ] for 2 or 4 PRBs if
% repetition is not configured and Table 6.8B.1-2 for all other cases.
% 
% * _Frequency Hopping -_ If the MPDCCH is repeated over multiple
% subframes, inter-subframe frequency hopping can be optionally applied
% where the hopping occurs for blocks of subframes of length 1,2,4,8 for
% devices in CE mode A and 2,4,8,16 in CE mode B. The hopping block
% length and hopping offset are cell-specific parameters. The frequency
% hopping can be over 2 narrowbands or 4 equally spaced narrowbands. The
% relative positions of the RBs carrying the MPDCCH within each hopping
% narrowbands remains the same.

%% PBCH Physical Layer Processing and Procedures
% Similar to the PDSCH, LTE-M uses the same physical broadcast channel
% (PBCH) as in the case of LTE but with optional repetitions. 
% 
% * _Core PBCH and Non-core PBCH -_ LTE-M PBCH is divided into two parts;
% the 'core' PBCH which is the normal LTE PBCH and is transmitted in the
% first subframe of every frame with 40ms periodicity. The non-core part is
% the LTE-M specific repetitions where the 'core' PBCH symbols are repeated
% up to 5 times depending on the duplex mode and cyclic prefix length.
% 
% * _Repetitions -_ PBCH repetitions occur in subframe 9 of the preceding
% frame and subframe 0 of the current radio frame for FDD as given by TS
% 36.211 Table 6.6.4-1 [ <#23 1> ]. For TDD, the repetitions occur in
% subframes 0 and 5 of the same radio frame as given by Table 6.6.4-2. The
% subcarriers remain the same for the core part and the repetitions. Note
% that unlike the core part, the PBCH repetitions should not map to REs
% used by CSI reference signals. The repetitions are defined according to
% the duplex mode and cyclic prefix length. For FDD, all PBCH core symbols
% are repeated 4 times if normal cyclic prefix and 3 times if extended
% cyclic prefix. For TDD, if extended cyclic prefix, all symbols are
% repeated 3 times. For TDD and normal cyclic prefix, PBCH core symbols 0
% and 1 are repeated 5 times and symbols 2 and 3 are repeated 3 times.

%% Simulation Settings
% This example is divided into the following steps:
%  
% * Configure the simulation parameters (cell-wide and MPDCCH/PDSCH specific)
% * Create and encode a DCI message payload for transmission on MPDCCH
% * Create and encode a DL-SCH payload for transmission on PDSCH
% * Generate the symbols for the MPDCCH subframe sequence and DM-RS, and
% map them into the resource elements of the multi-subframe resource grid
% * Generate the symbols for the LTE-M PDSCH subframe sequence, map them
% into the resource elements of the multi-subframe resource grid
% * Generate the symbols for the LTE-M PBCH subframe sequence, map them
% into the resource elements of the multi-subframe resource grid
% * Apply CP-OFDM modulation to final grid to create the associated 
% baseband waveform
% * Display plots of the resource grid and time-series waveform
% 
% In this first section, we specify the simulation parameters to be used in
% later sections for the DCI, MPDCCH and DM-RS creation. This example uses
% an LTE FDD carrier with bandwidth of 5MHz and normal cyclic prefix.
% Cell-wide settings are contained in the structure |enb|, MPDCCH specific
% parameters are contained in structure |mpdcch| and PDSCH specific
% parameters are contained in structure |pdsch|.
enb = struct();
enb.NDLRB = 25;                       % LTE carrier BW
enb.NCellID = 1;                      % The cell ID
enb.CellRefP = 1;                     % Number of cell-specific ports
enb.CFI = 3;                          % CFI indicator
enb.DuplexMode = 'FDD';               % Duplex mode
enb.TDDConfig = 1;                    % Uplink/Downlink configuration (TDD)
enb.CyclicPrefix = 'Normal';          % Cyclic prefix duration
enb.NSubframe = 0;                    % Subframe number
enb.NFrame = 0;                       % Frame number
enb.CSIRSPeriod = 'Off';              % CSI-RS period control
enb.CSIRSConfig = 0;                  % CSI-RS configuration
enb.CSIRefP = enb.CellRefP;           % Number of CSI-RS antenna ports
enb.ZeroPowerCSIRSPeriod = 'Off';     % Zero power CSI-RS period control
enb.ZeroPowerCSIRSConfig = 0;         % Zero power CSI-RS configuration
enb.Ng = 'Sixth';                     % HICH group multiplier
enb.PHICHDuration = 'Extended';       % PHICH duration

% Set up hopping specific parameters
enb.HoppingOffset = 1;% Hopping offset 1...maxAvailableNarrowbands (TS 36.331)
enb.NChDLNBhop = 2;   % Number of narrowbands over which MPDCCH/PDSCH hops (2 or 4)
enb.NChDLNB = 2;      % Number of subframes in one hop/hopping block length

%% 

% MPDCCH Configuration
mpdcch = struct();
mpdcch.Hopping = true;          % Enable/Disable frequency hopping (only for 1.4MHz)
mpdcch.NRepMPDCCH = 8;          % The total number of MPDCCH repetitions
mpdcch.EPDCCHECCE = [0 7];      % ECCE range used for this MPDCCH (8 ECCE) 
mpdcch.EPDCCHType = 'Localized';% Transmission type ('Localized', 'Distributed')
mpdcch.EPDCCHNID = 1;           % Cell ID/MPDCCH ID depending on search space type
mpdcch.EPDCCHStart = 4;         % MPDCCH start OFDM symbol in each subframe
mpdcch.RNTI = 1;                % RNTI for use with 'Localized' transmission

%%
% _MPDCCH Allocation -_ The (initial) set of PRBs used for the MPDCCH
% transmission is defined by a vector of 0-based PRB indices specifying the
% absolute positions of the PRB within the wideband carrier. These PRBs
% should fall within a valid narrowband. If frequency hopping is disabled
% for MPDCCH, an MPDCCH candidate will always be transmitted in the PRBs
% specified by the 'InitPRBSet' parameter. If frequency hopping is enabled
% for MPDCCH, an MPDCCH candidate will be transmitted in the same relative
% positions of PRBs, but in different narrowbands as defined in TS 36.211
% section 6.8B.5. For the 5MHz LTE carrier used in this example, there are
% four narrowbands as given by TS 36.211 section 6.2.7 [ <#23 1> ]. The
% first narrowband has PRBs 0...5, second has PRBs 6...11, third has PRBs
% 13...18 and the fourth has PRBs 19...24. All other PRBs within the 5MHz
% band fall outside the narrowbands and cannot be used for LTE-M
% transmission. In this example, we use MPDCCH format 2, where 8 ECCEs are
% used for the MPDCCH transmission. Each PRB slot pair consists of 4 ECCEs
% therefore we need to define a minimum allocation of 2 PRB. In this
% example, we select the 3rd and 4th PRBs in the first narrowband
mpdcch.InitPRBSet = (2:3)';         
mpdcch.InitNSubframe = 0; % Absolute subframe number of first MPDCCH subframe

%%

% PDSCH Configuration
pdsch = struct();
pdsch.Hopping = true;      % Enable/Disable frequency hopping (only for 1.4MHz)
pdsch.NRepPDSCH = 16;      % The total number of PDSCH repetitions
pdsch.CEMode = 'A';        % A for CE mode A and B for CE mode B
pdsch.TxScheme = 'Port0';  % Port 0 or TxDiversity or Spatial Mux or Port 7
pdsch.Modulation  = 'QPSK';% Modulation scheme (QPSK/16QAM)
pdsch.NLayers = 1;         % Number of layers
pdsch.RV = 0;              % Redundancy version for DL-SCH processing 
pdsch.RNTI = 1;            % RNTI used for the UE
pdsch.NSCID = 0;           % Scrambling identity
pdsch.TrBlkSizes = 100;    % Transport block size

%%
% _PDSCH Allocation -_ The PRB allocation is flexible in the case of CE
% mode A (signaled via DCI format 6-1A) and fixed in the case of CE mode B
% (signaled via DCI format 6-1B). In CE mode A, the allocation can be on 1
% to 6 PRBs within one or more narrowbands as defined by resource
% allocation type 2 or for the entire LTE carrier bandwidth via resource
% allocation type 0. In CE mode B, the allocation spans either the entire 6
% PRBs or the first 4 PRBs of the narrowband(s) configured. For Cat-M1
% devices, the transmission is in a single narrowband. For Cat-M2 devices,
% if the higher layer parameter |ce-pdsch-maxBandwidth-config| is set to
% 20MHz in CE mode B, the transmission can span multiple narrowbands and
% the overall allocation can be up to a maximum of 96 PRBs (grouped into
% widebands, where each wideband consists of 4 narrowbands). The widebands
% used are signaled via the wideband combination index field in the DCI as
% described in TS 36.213 Table 7.1.6-2 [ <#23 3> ]. If
% |ce-pdsch-maxBandwidth-config| is set to 5MHz, the transmission occurs in
% a single wideband consisting of 1,2,3 or 4 narrowbands depending on the
% LTE carrier bandwidth (NDLRB).
% 
% In this example, we specify the allocation using the |InitPRBSet|
% parameter and |InitNarrowbandIndex|. If frequency hopping is disabled,
% LTE-M PDSCH will always be transmitted in the PRBs specified by the
% |InitPRBSet| and |InitNarrowbandIndex| parameters. If frequency hopping
% is enabled, PDSCH will be transmitted in the same relative positions of
% PRBs, but in different narrowbands as defined in TS 36.211 section 6.4.1
% [ <#23 1> ]. If the allocation spans more than one narrowband or one or
% more widebands, the |InitNarrowbandIndex| should be a vector specifying
% the constituent narrowband indices.
% As an example, if |ce-pdsch-maxBandwidth-config| is 20MHz and the LTE-M
% transmission is within a 20MHz LTE carrier, there are 4 widebands
% (0,1,2,3) available for LTE-M PDSCH transmission with corresponding
% narrowband indices {(0 1 2 3) (4 5 6 7) (8 9 10 11) (12 13 14 15)}. If
% the desired allocation is widebands 2 & 3, then the |InitNarrowbandIndex|
% must be then set to [8 9 10 11 12 13 14 15].

pdsch.InitPRBSet = (1:2)';     % 0-based PRB index
pdsch.InitNarrowbandIndex = 0; % 0-based wideband index
% In this example, we disable frequency hopping when transmission is over 2
% or more narrowbands
if numel(pdsch.InitNarrowbandIndex) > 1
    pdsch.Hopping = false; 
    mpdcch.Hopping = false;
end

%%
% Enable or disable PBCH repetitions
enb.RepPBCHEnable = true;

% Specify the power scaling in dB for MPDCCH, MPDCCH DM-RS, PDSCH and
% reference signals (Cell RS or DM-RS)
mpdcch.MPDCCHPower = 30;
mpdcch.MPDCCHDMRSPower = 32;
pdsch.Rho = 25;
pdsch.RSPower = 80;
% Power levels for the PBCH core and reps parts
enb.PBCHPower = 33;
enb.PBCHRepsPower = 36;
% Power level for the PBCH Cell RS reps
enb.PBCHCellRSRepsPower = 28;

%%
% Total subframes to simulate (all downlink subframes are BL/CE subframes)
% and the MPDCCH and PDSCH are transmitted without any subframe gaps
totmtcSubframes = mpdcch.InitNSubframe+mpdcch.NRepMPDCCH+2+pdsch.NRepPDSCH;
% Identify all downlink subframes in a frame
info = arrayfun(@(x)lteDuplexingInfo(setfield(enb,'NSubframe',x)),0:9); 
dlsfs = arrayfun(@(x)strcmpi(x.SubframeType,'Downlink'),info);

% Total absolute subframes to simulate
sfsnumlastFrame = getlastabsSF(dlsfs,totmtcSubframes);
totSubframes = floor(totmtcSubframes/sum(dlsfs)) *10 + sfsnumlastFrame;

% Absolute subframe number of first PDSCH subframe, this would be two
% subframes after the MPDCCH subframes (assuming no non BL/CE subframes)
lastSfForMPDCCHPlus2 = getlastabsSF(dlsfs,mpdcch.NRepMPDCCH + 2); % Last subframe number in last frame for MPDCCH+2
pdsch.InitNSubframe = mpdcch.InitNSubframe + floor((mpdcch.NRepMPDCCH + 2)/sum(dlsfs)) *10 + lastSfForMPDCCHPlus2;

% Find the last absolute subframe for MPDCCH transmission
lastSfForMPDCCH = getlastabsSF(dlsfs,mpdcch.NRepMPDCCH); % Last subframe number in last frame for MPDCCH
mtclastabsSfForMPDCCH = mpdcch.InitNSubframe + floor((mpdcch.NRepMPDCCH)/sum(dlsfs)) *10 + lastSfForMPDCCH;

%% DCI Message Encoding
% The bit vector |dciBits| is passed to the function |lteDCIEncode| which
% performs CRC masking and insertion, tail-biting convolutional coding and
% rate matching, following TS 36.212 sections 5.3.3.2 to 5.3.3.4. Note that
% the third argument to |lteDCIEncode| specifies the rate matching output 
% size equal to the MPDCCH data bit capacity in a subframe. Here we use a
% dummy 26 bit DCI message of all ones, corresponding to a DCI Format 6-1A
% message as specified in TS 36.212 section 5.3.3.1.12.

% Find the MPDCCH data bit capacity
[~,info] = lteEPDCCHIndices(enb,setfield(mpdcch,'EPDCCHPRBSet',mpdcch.InitPRBSet)); %#ok<SFLD>
% Define DCI message bits
dciBits = ones(26,1);   
% Create the coded DCI bits
codedDciBits = lteDCIEncode(mpdcch,dciBits,info.EPDCCHG);

%% DL-SCH Encoding

% Find the LTE-M PDSCH data bit capacity, this should not include the PBCH,
% PSS, SSS and CSI-RS REs. So we select the subframe 9 which is a DL
% subframe in both FDD and TDD duplex modes (Note: subframe 9 is not DL for
% TDDConfig 0, TDDConfig 0 does not have a 'normal' DL subframe)
fullPDSCHsf = 9;

[~,fullInfo] = ltePDSCHIndices(setfield(enb,'NSubframe',fullPDSCHsf),pdsch,getPDSCHAllocation(enb,pdsch));  %#ok<SFLD>
% Define DL-SCH message bits
trData = ones(pdsch.TrBlkSizes(1),1);   
% Create the coded DL-SCH bits
codedTrBlock = lteDLSCH(enb,pdsch,fullInfo.G,trData);

%% MPDCCH Generation
% In this example, we use the localized type with MPDCCH format 2 and 2
% PRBs. MPDCCH with 2 or 4 PRBs and no repetitions use the same format
% table as the EPDCCH (TS 36.211 Table 6.8A.1-2). For all other cases, the
% formats are given by TS 36.211 Table 6.8B.1-2. Also with CE mode A, no
% repetitions and all LTE-M subframes, the scrambling gets initialized
% every subframe as for the EPDCCH and the |cinit| is the same (because
% |Nacc| = 1 for |CEmodeA| and |NabsMPDCCH| = 1). All other processing
% stages i.e. symbol modulation, layer mapping, precoding and mapping to
% resource elements are the same for EPDCCH and MPDCCH. Hence, we use the
% EPDCCH functions to generate the MPDCCH symbols and indices.

% Number of subframes in a scrambling block
Nacc = 1;
if strcmpi(enb.DuplexMode,'FDD') && mpdcch.NRepMPDCCH >= 4
    Nacc = 4;
elseif strcmpi(enb.DuplexMode,'TDD') && mpdcch.NRepMPDCCH >= 10
    Nacc = 10;
end

% Create a resource grid for the entire transmission. The MPDCCH, PDSCH and
% DM-RS symbols will be mapped in this array. Note that we are creating the
% grid for 4 antenna planes as the MPDCCH transmission can be sent on ports
% selected from the set (107, 108, 109 and 110)
subframeSize = lteDLResourceGridSize(enb,4);
sfgrid = zeros([subframeSize(1) subframeSize(2)*totSubframes subframeSize(3:end)]);

mpdcchSym = []; % Initialize MPDCCH symbols
mpdschSym = []; % Initialize PDSCH symbols
mpbchCoreSymFull = [];  % Initialize PBCH symbols
startSubframe = enb.NFrame*10+enb.NSubframe; % Initial absolute subframe number
for sf = startSubframe + (0:totSubframes -1)
    
    % Set current absolute subframe and frame numbers  
    enb.NSubframe = mod(sf,10);
    enb.NFrame = floor((sf)/10);
    
    % Skip processing if this is not a downlink subframe
    duplexInfo = lteDuplexingInfo(enb);
    if ~strcmpi(duplexInfo.SubframeType,'Downlink')
        continue
    end
        
    % Transmitting the MPDCCH
    if (sf >= mpdcch.InitNSubframe) && (sf < mtclastabsSfForMPDCCH)
        % Calculate the PRBSet used in the current subframe
        prbset = getHoppingAllocation(enb,mpdcch);

        % Calculate the MPDCCH indices for the current subframe
        mpdcch.EPDCCHPRBSet = prbset;
        [mpdcchIndices,info] = lteEPDCCHIndices(enb,mpdcch); 

        % Create an empty subframe grid
        subframe = lteDLResourceGrid(enb,4);

        % Encode MPDCCH symbols from DCI codeword
        % In the case of repetition, the same symbols are repeated in each of 
        % a block of NRepMPDCCH subframes. Frequency hopping is applied as required
        if ~mod(sf,Nacc) || isempty(mpdcchSym)
            mpdcchSym = lteEPDCCH(enb,mpdcch,codedDciBits)*db2mag(mpdcch.MPDCCHPower); 
        end
        % Map MPDCCH symbols to the subframe grid
        subframe(mpdcchIndices) = mpdcchSym;

        % Create MPDCCH DM-RS   
        % The MPDCCH and its reference symbols are transmitted on the same
        % port(s) and is transmitted only on the PRBs in which the
        % corresponding MPDCCH is mapped. The DM-RS sequence is the same as for
        % the EPDCCH as given by the equations in TS 36.211 section 6.10.3A
        mpdcchDMRS = lteEPDCCHDMRS(enb,mpdcch)*db2mag(mpdcch.MPDCCHDMRSPower); % MPDCCH DM-RS symbols
        mpdcchDMRSIndices = lteEPDCCHDMRSIndices(enb,mpdcch); % MPDCCH DM-RS indices
        subframe(mpdcchDMRSIndices) = mpdcchDMRS;   % Map DM-RS signals to the grid

        % Now assign the current subframe into the overall grid
        sfgrid(:,(1:subframeSize(2))+sf*subframeSize(2),:) = subframe;
    end
    
    
    %% BL/CE PDSCH Generation
    % For the LTE-M PDSCH, the PBCH, PSS, SSS and CSI-RS RE locations are
    % counted in the mapping, but not used in the transmission. This means
    % that the rate matched capacity should include these RE locations, but
    % the symbols for these locations are not transmitted. So we create the
    % codeword accordingly and puncture the symbols corresponding to the
    % conflicting locations
    if (sf >= pdsch.InitNSubframe)

        % Calculate the PRBSet used in the current subframe
        prbset = getPDSCHAllocation(enb,pdsch);

        % Calculate the PDSCH indices for the current subframe
        pdsch.PRBSet = prbset;
        mpdschIndices = ltePDSCHIndices(enb,pdsch,pdsch.PRBSet); 
        % If the subframe contains PBCH, PSS, SSS, CSI-RS or Zero Power
        % CSI-RS REs, then we need to puncture the corresponding symbols
        % from the mapping but the rate matching should be to the full
        % PDSCH capacity ignoring the possible presence of these symbols.
        % This is done by setting the subframe and TDDConfig (if TDD mode)
        % to a subframe containing no PBCH, PSS and SSS and turning off the
        % CSI-RS and ZP CSI-RS. The full set of possible PDSCH indices are
        % recalculated every subframe as these can change when frequency
        % hopping
        enbTemp = enb;                          
        enbTemp.TDDConfig = 1;              % TDDConfig 0 has no full PDSCH subframe
        enbTemp.NSubframe = fullPDSCHsf;    % Set the subframe to a full PDSCH subframe
        enbTemp.CSIRSPeriod = 'Off';        % CSI-RS period control
        enbTemp.ZeroPowerCSIRSPeriod = 'Off'; % Zero power CSI-RS period control
        mpdschIndicesFull = ltePDSCHIndices(enbTemp,pdsch,pdsch.PRBSet);
        [~, txmpdschIndicesPositions] = intersect(mpdschIndicesFull,mpdschIndices); 

        % Create an empty subframe grid
        subframe = lteDLResourceGrid(enb,4);

        % Encode PDSCH symbols from the codeword
        % In the case of repetition, the same symbols are repeated in each of 
        % a block of NRepPDSCH subframes. Frequency hopping is applied as required
        if ~mod(sf,Nacc) || isempty(mpdschSym)
            mpdschSym = ltePDSCH(enb,pdsch,codedTrBlock)*db2mag(pdsch.Rho); 
        end
        % Map punctured PDSCH symbols to the subframe grid
        subframe(mpdschIndices) = mpdschSym(txmpdschIndicesPositions);

        % Transmit UE-specific reference signal (DM-RS) if applicable
        if any(strcmpi(pdsch.TxScheme,{'Port5' 'Port7-8' 'Port8' 'Port7-14'}))
            ueRSIndices = lteDMRSIndices(enb,pdsch);
            ueRSSymbols = lteDMRS(enb,pdsch);
            subframe(ueRSIndices) = ueRSSymbols*db2mag(pdsch.RSPower);  % Map symbols to the grid  
        end

        % Now assign the current subframe into the overall grid
        sfgrid(:,(1:subframeSize(2))+sf*subframeSize(2),:) = subframe;
    end
    
    %% BL/CE PBCH Generation
    % PBCH symbol generation and mapping on REs of a resource grid. LTE-M
    % PBCH consists of the normal LTE 'core' part and the LTE-M specific
    % repetitions. Core PBCH symbols are only present in first subframe
    % with a periodicity of 4 frames.
    
    subframe = sfgrid(:,(1:subframeSize(2))+sf*subframeSize(2),:);
    if(mod(enb.NSubframe,10)==0)
        % Generate symbols if its the first simulated frame or
        % when mod(NFrame,4) is 0;
        if ~mod(enb.NFrame,4) || isempty(mpbchCoreSymFull) 
            mpbchCoreSymFull = getMPBCHCore(enb);
        end
        mpbchCoreIndices = ltePBCHIndices(enb,{'1based'});
        % Now extract out the core part for the Frame
        mpbchCoreSym = mpbchCoreSymFull(:,mod(enb.NFrame,4)+1);
        % Map the PBCH core symbols to the subframe
        subframe(mpbchCoreIndices) = mpbchCoreSym*db2mag(enb.PBCHPower);
        
        % Now assign the current subframe into the overall grid
        sfgrid(:,(1:subframeSize(2))+sf*subframeSize(2),:) = subframe;
        
        % Get the cell RS symbols and indices to be repeated if PBCH
        % repetitions are enabled
        [mpbchCoreCellRSSymbols,mpbchCoreCellRSIndices] = getPBCHCoreCellRS(enb);
        
    elseif enb.RepPBCHEnable && strcmpi(enb.DuplexMode,'FDD') && (mod(enb.NSubframe,10)==9)
        % If this is the 9th subframe in FDD mode, then create the core
        % symbols and indices for the next frame to be used for PBCH
        % repetitions in this subframe
        enbNext = enb;
        enbNext.NSubframe = 0;
        enbNext.NFrame = enbNext.NFrame+1; % Advance to the next frame
        % if the current frame contained the last PBCH block, then we need
        % the new set of PBCH symbols
        if mod(enb.NFrame,4)==3
            mpbchCoreSymFull = getMPBCHCore(enbNext);
        end
        % Now extract out the core part for the Frame
        mpbchCoreSym = mpbchCoreSymFull(:,mod(enbNext.NFrame,4)+1);
        mpbchCoreIndices = ltePBCHIndices(enbNext,{'1based'});
        [mpbchCoreCellRSSymbols,mpbchCoreCellRSIndices] = getPBCHCoreCellRS(enbNext);
    end
    % PBCH repetition part if enabled
    if (enb.RepPBCHEnable)
        % Get the PBCH repetition part consisting of repeating PBCH symbols
        % and repeating Cell RS signals and corresponding indices
        [pbchrepSymbols, pbchrepIndices, pbchCellRSrepSymbols, pbchCellRSrepIndices] = getPBCHRep(enb,mpbchCoreSym,mpbchCoreIndices,mpbchCoreCellRSSymbols,mpbchCoreCellRSIndices);
        % Map the PBCH repetitions to the grid
        subframe(pbchrepIndices) = pbchrepSymbols*db2mag(enb.PBCHRepsPower);
        % Map the Cell RS repetitions to the grid
        subframe(pbchCellRSrepIndices) = pbchCellRSrepSymbols*db2mag(enb.PBCHCellRSRepsPower);
    end
    
    % Now assign the current subframe into the overall grid
    sfgrid(:,(1:subframeSize(2))+sf*subframeSize(2),:) = subframe;

end

%% Create Time Domain Baseband Waveform 
% Create the time domain baseband waveform by OFDM modulating the
% resource grid. The resulting matrix has four columns; one of which will
% contain the complex baseband time-domain waveform samples for the MPDCCH
waveform = lteOFDMModulate(enb,sfgrid);

%% Plot Transmitted Grid and Baseband Waveform
% Plot the grid and time domain baseband waveform. If the transmission uses
% more than one port, only the first port is shown. Note that the resource
% grid plot uses the power levels of the individual channels and signals to
% assign colors to the resource elements.

% Create an image of overall resource grid
% Plot the port used by MPDCCH along with the first port for all other channels
figure
im = image(abs(sfgrid(:,:,info.EPDCCHPorts(1))+ sfgrid(:,:,1))); 
cmap = parula(64);
colormap(im.Parent,cmap);
axis xy;
title(sprintf('LTE-M CEMode%s Downlink RE Grid (NRepMPDCCH = %d, NRepPDSCH = %d)',pdsch.CEMode,mpdcch.NRepMPDCCH,pdsch.NRepPDSCH)) 
xlabel('OFDM symbols')
ylabel('Subcarriers')
% Create the legend box to indicate the channel/signal types associated with the REs
reNames = {'MPDCCH';'MPDCCH DRS';'PDSCH';'PBCH Core'; 'PBCH Reps'; 'Cell RS Reps'};
clevels = round(db2mag([mpdcch.MPDCCHPower mpdcch.MPDCCHDMRSPower  pdsch.Rho enb.PBCHPower enb.PBCHRepsPower enb.PBCHCellRSRepsPower]));
% If using DM-RS, include in legend
if any(strcmpi(pdsch.TxScheme,{'Port5' 'Port7-8' 'Port8' 'Port7-14'}))
    reNames{end+1} = 'DMRS';
    clevels(end+1) = pdsch.RSPower;
end
N = numel(reNames);
L = line(ones(N),ones(N), 'LineWidth',8); % Generate lines                   
% Set the colors according to cmap
set(L,{'color'},mat2cell(cmap( min(1+clevels,length(cmap) ),:),ones(1,N),3));   % Set the colors according to cmap
legend(reNames{:});

% Create separate plots of the control/data waveforms
figure
plot(abs(waveform(:,info.EPDCCHPorts(1))))
title('MPDCCH Time Domain Waveform') 
xlabel('Samples')
ylabel('Amplitude')
figure
plot(abs(waveform(:,1)))
title('PBCH and PDSCH time domain waveform') 
xlabel('Samples')
ylabel('Amplitude')

%% Local Functions
% The following local functions are used in this example:
%
% * |calcNarrowbandPRBSets| - Calculate narrowbands and associated PRBs
% * |getHoppingAllocation|  - Calculate the subframe allocation
% * |getPDSCHAllocation|    - Calculate the PDSCH allocation
% * |getPBCHCore|           - Calculate the core PBCH symbols and indices
% * |getPBCHCoreCellRS|     - Calculate the core PBCH symbols and indices
% * |getPBCHRep|            - Calculate the PBCH repetition part


%% Selected Bibliography
% # 3GPP TS 36.211 "Physical channels and modulation"
% # 3GPP TS 36.212 "Multiplexing and channel coding"
% # 3GPP TS 36.213 "Physical layer procedures"
% # 3GPP TS 36.331 "Radio Resource Control (RRC) Protocol specification"
% # O. Liberg, M. Sundberg, Y.-P. Wang, J. Bergman and J. Sachs, Cellular Internet of Things: Technologies, Standards and Performance, Elsevier, 2018.
% # E. Dahlman, S. Parkvall and J Skold 4G LTE-Advanced Pro and The Road to 5G


%% Local Functions

% Calculate the widebands, narrowbands and PRBSets for the LTE carrier bandwidth
function [prbsets,nNB,nWB] = calcNarrowbandPRBSets(NDLRB)
    % Narrowbands & Widebands (See 36.211 section 6.2.7)
    NDLNB = floor(NDLRB/6);
    nNB = 0:(NDLNB-1); % Narrowbands
    if NDLNB >= 4
        NDLWB = floor(NDLNB/4);
    else
        NDLWB = 1;
    end
    nWB = 0:(NDLWB-1); % Widebands
    
    % PRBs in a narrowband
    ii = 0:5;
    ii0 = floor(NDLRB/2) - 6*(NDLNB/2);
    prbsets = zeros(6,numel(nNB));
    for nb = 1:numel(nNB)
        if mod(NDLRB,2) && nNB(nb)>= (NDLNB/2)
            prbsets(:,nb) = 6*(nNB(nb))+ii0+ii + 1;
        else
            prbsets(:,nb) = 6*(nNB(nb))+ii0+ii;
        end
    end
end

% Calculate the resource blocks allocated in the hopping narrowband
function prbset = getHoppingAllocation(enb,chs)
    
    % If frequency hopping is disabled, the allocation is same as initial
    if ~chs.Hopping
        prbset = chs.InitPRBSet;
        return
    end
    
    % Hopping narrowband calculation according to TS 36.211 section 6.8B.5
    nNBi0ss = 0;
    % Get the possible narrowbands and associated PRBSets
    if strcmpi(enb.DuplexMode,'FDD')
        idelta = 0;
    else
        idelta = enb.NChDLNB-2;
    end
    j0 = floor((chs.InitNSubframe+idelta)/enb.NChDLNB);
    % Get the narrowbands and corresponding resources
    [prbsets,nNB] = calcNarrowbandPRBSets(enb.NDLRB);
    % Calculate the narrowband for this subframe
    enb.NSubframe = enb.NFrame*10+enb.NSubframe; % Get the absolute subframe number
    nnBi = mod( (nNBi0ss + (mod(floor((enb.NSubframe+idelta)/enb.NChDLNB - j0),enb.NChDLNBhop))*enb.HoppingOffset) ,numel(nNB));
    % Calculate the PRBSet for this subframe, they are on the same RBs
    % within the narrowband
    [rbstartIndex,nbstartIndex] = find(prbsets == chs.InitPRBSet(1));
    [rbendIndex,nbendIndex] = find(prbsets == chs.InitPRBSet(end));
    if (isempty(rbstartIndex) || isempty(rbendIndex)) || (nbstartIndex ~= nbendIndex)
       error('Invalid PRBSet specified, must be resources within single narrowband'); 
    end
    prbset = prbsets(rbstartIndex:rbstartIndex+numel(chs.InitPRBSet)-1,nnBi+1);

end

% Calculate the PDSCH allocation
function prbset = getPDSCHAllocation(enb,PDSCH)
    if PDSCH.Hopping
        % Cat-M1 mode with hopping
        prbset = getHoppingAllocation(enb,PDSCH);
    else
        % Calculate the allocations in narrowband(s)
        [prbsets,nNB] = calcNarrowbandPRBSets(enb.NDLRB);
        % Calculate the PRBSet for this subframe, they are on the same RBs
        % within all narrowbands
        rbstartIndex = mod(find(prbsets == PDSCH.InitPRBSet(1))-1,6)+1;
        rbendIndex = mod(find(prbsets == PDSCH.InitPRBSet(end))-1,6)+1;
        if isempty(rbstartIndex) || isempty(rbendIndex)
           error('Invalid PRBSet specified, must be resources within narrowbands'); 
        end
        if any(PDSCH.InitNarrowbandIndex > max(nNB))
           error('Invalid InitNarrowbandIndex specified, must be from the set 0...%d',max(nNB)); 
        end
        prbset = prbsets(rbstartIndex:rbendIndex,PDSCH.InitNarrowbandIndex+1);
        prbset = prbset(:);

    end

end

% Calculate the Cell RS REs and symbols corresponding to the 'core' PBCH
% part
function [pbchCoreCellRSSymbols,pbchCoreCellRSIndices] = getPBCHCoreCellRS(enb)
   
    % We need to repeat the cell reference signals within the (k,l) region
    NscRB = 12;
    k = (enb.NDLRB*NscRB)/2 -36 + (0:71) + 1; % 1-based full possible PBCH subcarrier locations
    if strcmpi(enb.CyclicPrefix,'Normal')
        NsymbDL = 7;
    else
        NsymbDL = 6;
    end
    l = NsymbDL+ (0:3)+ 1; % 1-based OFDM symbol numbers in the subframe corresponding to PBCH core part

    % NOTE: The cell RS symbols and indices can be looked up from the
    % grid if provided or can be created here as shown below
    cellRSIndices = lteCellRSIndices(enb);
    cellRSSymbols = lteCellRS(enb);
    rsgrid = lteDLResourceGrid(enb);
    rsgrid(cellRSIndices) = cellRSSymbols;
    % Now remove all RS symbols outside of the core PBCH band
    excludeSubs = setdiff(1:enb.NDLRB*NscRB,k);
    excludeofdmSymbols = setdiff(1:NsymbDL*2,l);
    % Now remove all the unwanted RE locations
    rsgrid(:,excludeofdmSymbols,:) = 0;
    rsgrid(excludeSubs,:,:) = 0;

    % What is in the grid is the RS symbols to be repeated
    pbchCoreCellRSIndices = find(rsgrid);
    pbchCoreCellRSSymbols = rsgrid(pbchCoreCellRSIndices);

end

% Calculate the PRBCH and Cell RS REs and symbols corresponding to the
% repetition part
function [pbchrepSymbols,pbchrepIndices, pbchCellRSrepSymbols, pbchCellRSrepIndices] = getPBCHRep(enb,pbchCoreSymbols,pbchCoreIndices,pbchCoreCellRSSymbols,pbchCoreCellRSIndices)
    pbchrepIndices = [];
    pbchrepSymbols = [];
    symMappings = {};
    pbchCellRSrepIndices = [];
    pbchCellRSrepSymbols = [];
    
    % For both FDD and TDD modes, there is no repetition if NDLRB = 6
    if enb.NDLRB==6
        return
    end

    % Get the subcarriers for the PBCH core part
    [pbchCoreSubcarriers,ofdmSymbols,~] = ind2sub(lteDLResourceGridSize(enb),pbchCoreIndices);
    % Get the subcarriers for the Cell RS core part
    [pbchCellRSCoreSubcarriers,ofdmSymbolsCellRS,~] = ind2sub(lteDLResourceGridSize(enb),pbchCoreCellRSIndices);
       
    % FDD reps only in subframes 9 (frame n-1) and 0 (frame n) and TDD only
    % reps in subframes 0 and 5 in the same frame
    % Get the subframe symbol numbers in which the reps go onto
    if strcmpi(enb.DuplexMode,'FDD') 
        if strcmpi(enb.CyclicPrefix,'Normal')
            NsymbDL = 7;
            if (mod(enb.NSubframe,10) == 0) 
                symMappings = { 5 ;
                               12 ; 
                               13 ;
                               [4 14]};
            elseif (mod(enb.NSubframe,10)==9)
                symMappings = { [4 8 12] ;
                                [5 9 13] ; 
                                [6 10 14] ;
                                [7 11]};
            end
        else
            NsymbDL = 6;
            if (mod(enb.NSubframe,10) == 0) 
                symMappings = {[] ;
                               4  ; 
                               11 ;
                               12};
            elseif (mod(enb.NSubframe,10)==9)
                symMappings = { [4 7] ;
                                [5 8] ; 
                                [6 9] ;
                                [10 11]};
            end
        end
    
    else
        if strcmpi(enb.CyclicPrefix,'Normal')
            NsymbDL = 7;
            if (mod(enb.NSubframe,10) == 0) 
                symMappings = { [4 12]  ;
                                [5 13] ; 
                                6 ;
                                7};
            elseif (mod(enb.NSubframe,10)==5) && enb.NDLRB>15
                symMappings = { [4 8 12] ;
                                [5 9 13] ; 
                                [6 10] ;
                                [7 11]};
            end
        else
            NsymbDL = 6;
            if (mod(enb.NSubframe,10) == 0) 
                symMappings = {4 ;
                               5 ; 
                               6 ;
                               11};
            elseif (mod(enb.NSubframe,10)==5) && enb.NDLRB>15
                symMappings = { [4 7] ;
                                [5 8] ; 
                                [6 9] ;
                                [10 11]};
            end
        end

    end
    
    % If this is a repetition subframe, find the indices
    if ~isempty(symMappings)

        % Create an empty subframe grid
        sfgrid = lteDLResourceGrid(enb);
        sfgridRS = lteDLResourceGrid(enb);
        for osymb = 1:4 % For all 4 PBCH symbols
            % Extract out each core symbol to map to one or more OFDM
            % symbols
            coreOFDMsymb = pbchCoreSymbols(ofdmSymbols==(osymb+NsymbDL));
            coreOFDMsymbRS = pbchCoreCellRSSymbols(ofdmSymbolsCellRS==(osymb+NsymbDL));
            
            % Map to all new repetition OFDM symbols in the current
            % subframe
            for m = 1:numel(symMappings{osymb,1})
                % create the indices for the current symbol (subcarriers
                % are the same as core symbols)
                symtoMap = symMappings{osymb,1}(m);
                sfgrid(pbchCoreSubcarriers(ofdmSymbols==(osymb+NsymbDL)),symtoMap,:) = coreOFDMsymb;
                sfgridRS(pbchCellRSCoreSubcarriers(ofdmSymbolsCellRS==(osymb+NsymbDL)),symtoMap,:) = coreOFDMsymbRS;
                
            end
            
        end
        
        % As per TS 36.211 section 6.6.4, the PBCH repetitions and cell RS
        % repetitions are punctured by CSI (& ZP CSI) RS signals. So clear
        % these positions
        csirsIndices = lteCSIRSIndices(enb);
        sfgrid(csirsIndices) = 0;
        sfgridRS(csirsIndices) = 0;
        
        % Now get the PBCH repeating symbols and indices
        pbchrepIndices = find(sfgrid);
        pbchrepSymbols = sfgrid(pbchrepIndices);
        % Now get the CellRS repeating symbols and indices
        pbchCellRSrepIndices = find(sfgridRS);
        pbchCellRSrepSymbols = sfgridRS(pbchCellRSrepIndices);
        
    end
end

% Get the MPBCH Core part symbols
function mpbchCoreSym = getMPBCHCore(enb)

    bchBits = lteMIB(enb);
    pbchBits = lteBCH(enb,bchBits);
    mpbchCoreSym = ltePBCH(enb,pbchBits);
    % Reshape to the four parts to go on to 4 frames
    mpbchCoreSym = reshape(mpbchCoreSym,numel(mpbchCoreSym)/4,4);
end

% Get the absolute subframe number in a frame which is used for the last
% transmission of a channel
function sfsnumlastFrame = getlastabsSF(dlsfs,totmtcSubframes)
    sfslastFrame = mod(totmtcSubframes,sum(dlsfs)); % subframes to tx in the last frame
    if sfslastFrame
        % Find the subframe number corresponding to the last subframe to transmit
        sfsnumlastFrame = find(dlsfs,sfslastFrame);
        sfsnumlastFrame = sfsnumlastFrame(end);
    else
        % No partial frames required
        sfsnumlastFrame = 0; 
    end

end
