% umtsDownlinkReferenceChannels UMTS Downlink measurement channels definition
%   DEF = umtsDownlinkReferenceChannels(...) returns DEF, a structure
%   containing the parameters required to generate a downlink measurement
%   channel waveform using the <a href="matlab:help('umtsDownlinkWaveformGenerator')">umtsDownlinkWaveformGenerator</a>.
%   This function generates the configuration structures for the Reference
%   Measurement Channels (RMC), Fixed Reference Channels (FRC) H-Sets and
%   Test Models. The RMC configurations are defined in TS25.101 Annex A.3
%   and the FRC H-Set configurations are defined in TS25.101 Annex A.7. The
%   Test Models are defined in TS25.141 Section 6.1.1.
%   
%   DEF = umtsDownlinkReferenceChannels(RC) returns the downlink
%   configuration structure for the measurement channel specified by RC:
%   'RMC0kbps', 'RMC12.2kbps', 'RMC64kbps', 'RMC144kbps', 'RMC384kbps',
%   'H-Set1', 'H-Set2', 'H-Set3', 'H-Set4', 'H-Set5', 'H-Set6', 'H-Set7',
%   'H-Set8', 'H-Set10', 'H-Set12', 'TM1_4DPCH', 'TM1_8DPCH', 'TM1_16DPCH',
%   'TM1_32DPCH', 'TM1_64DPCH', 'TM2_3DPCH', 'TM3_4DPCH', 'TM3_8DPCH',
%   'TM3_16DPCH', 'TM3_32DPCH', 'TM4', 'TM5_4DPCH_4HSPDSCH',
%   'TM5_6DPCH_2HSPDSCH', 'TM5_14DPCH_4HSPDSCH', 'TM5_30DPCH_8HSPDSCH',
%   'TM6_4DPCH_4HSPDSCH', 'TM6_30DPCH_8HSPDSCH'. In the case of H-Sets with
%   more than one configuration corresponding to different modulation
%   schemes, the first entry in the definition table will be used.
% 
%   The fields of the output structure DEF are described in 
%   <a href="matlab:doc('umtsDownlinkWaveformGenerator')">umtsDownlinkWaveformGenerator</a>.
%
%   DEF = umtsDownlinkReferenceChannels(RC,HSETMODULATION) is the same as
%   above except it allows optional control of the H-Set modulation type
%   HSETMODULATION. HSETMODULATION can be 'QPSK', '16QAM' or '64QAM', the
%   allowed values depend on the H-Set number. For RMC and Test Model
%   definitions, HSETMODULATION if specified, is ignored. If HSETMODULATION
%   is empty, the function output will be the same as the one argument
%   function signature above.
% 
%   Note that all the definitions are configured with RRC filtering and
%   oversampling set to 4.
% 
%   Example:
%   The example shows the generation of FRC H-Set1 configuration and how
%   this is used by umtsDownlinkWaveformGenerator.
%
%   config = umtsDownlinkReferenceChannels('H-Set1','16QAM');
%   waveform = umtsDownlinkWaveformGenerator(config);
%
%   See also umtsDownlinkWaveformGenerator, umtsUplinkReferenceChannels.

%    Copyright 2014-2023 The MathWorks, Inc.

function config = umtsDownlinkReferenceChannels(rc,modulation)
    % validate the measurement channel
    validateUMTSParameter('DLRMC',rc);
    if nargin==2
        if ~isempty(modulation)
            % Validate modulation if it is non-empty
            validateUMTSParameter('DLModulation',modulation);
        end
    else
        modulation = []; 
    end
    config = getDLBaseConfig();
    if any(strcmpi(rc,{'RMC0kbps', 'RMC12.2kbps', 'RMC64kbps', 'RMC144kbps', 'RMC384kbps'}))   
        % Get RMC Definition
        config = getDLRMCConfig(config,rc);
    elseif any(strcmpi(rc,{'H-Set1', 'H-Set2', 'H-Set3', 'H-Set4','H-Set5', 'H-Set6', 'H-Set7', 'H-Set8', 'H-Set10', 'H-Set12'}))      
        % Get FRC Definition
        config = getDLFRCConfig(config,rc,modulation);
    else
        % Get Test Model Definition
        config = getDLTMConfig(config,rc);    
    end

end


% Define the base configuration from which all RMCs, FRCs and TMs are
% defined, so that the order of parameters is always the same
function config = getDLBaseConfig()
    % cell wide settings
    config.TotFrames = 1;
    config.PrimaryScramblingCode = 0;
    config.FilterType = 'RRC';
    config.OversamplingRatio = 4;
    config.NormalizedPower = 'Off'; 

    % Define DPCH
    config.DPCH.Enable = 'On';
    config.DPCH.SlotFormat = 11;
    config.DPCH.SpreadingCode = 6; 
    config.DPCH.NMulticodes = 1;
    config.DPCH.SecondaryScramblingCode = 0; 
    config.DPCH.TimingOffset = 0;
    config.DPCH.Power = 0; % Power in dB
    config.DPCH.TPCData = 0;
    config.DPCH.TFCI = 0;
    config.DPCH.DataSource = 'CCTrCH'; 
    % Define CCTrCH containing DTCH and DCCH
    % Build DTCH definition
    TrCH(1).Name = 'DTCH';
    TrCH(1).CRC = '16';
    TrCH(1).CodingType = 'conv3';
    TrCH(1).RMA = 256;
    TrCH(1).TTI = 20;
    TrCH(1).DataSource = 'PN9-ITU';
    TrCH(1).ActiveDynamicPart = 1; % Index to active dynamic part
    TrCH(1).DynamicPart(1) = struct('BlockSize',244,'BlockSetSize',244);   % 1x244 length block
    % Build DCCH definition
    TrCH(2).Name = 'DCCH';
    TrCH(2).CRC = '12';
    TrCH(2).CodingType = 'conv3';
    TrCH(2).RMA = 256;
    TrCH(2).TTI = 40; 
    TrCH(2).DataSource = 'PN9-ITU';
    TrCH(2).ActiveDynamicPart = 1; % Index to active dynamic part
    TrCH(2).DynamicPart(1) = struct('BlockSize',100,'BlockSetSize',100);   % 1x100 length block
    % Finalize CCTrCH using the above
    config.DPCH.CCTrCH.Name = 'DCH';
    config.DPCH.CCTrCH.DTXPosition = 'fixed';
    config.DPCH.CCTrCH.TrCH(1) = TrCH(1);
    config.DPCH.CCTrCH.TrCH(2) = TrCH(2);
    
    % Define P-CCPCH
    config.PCCPCH.Enable = 'On'; 
    config.PCCPCH.Power = 0;
    config.PCCPCH.DataSource = 'CCTrCH'; 
    % BCH config
    config.PCCPCH.CCTrCH.Name = 'BCH';
    config.PCCPCH.CCTrCH.DTXPosition = 'fixed';
    config.PCCPCH.CCTrCH.TrCH.Name = 'BCH';
    config.PCCPCH.CCTrCH.TrCH.CRC = '16';
    config.PCCPCH.CCTrCH.TrCH.CodingType = 'conv2';
    config.PCCPCH.CCTrCH.TrCH.RMA = 256;
    config.PCCPCH.CCTrCH.TrCH.TTI = 20; 
    config.PCCPCH.CCTrCH.TrCH.DataSource = 'PN9-ITU';
    config.PCCPCH.CCTrCH.TrCH.ActiveDynamicPart = 1; % Index to active dynamic part
    config.PCCPCH.CCTrCH.TrCH.DynamicPart(1) = struct('BlockSize',246,'BlockSetSize',246);   % 1x246 length block
    
    % Define S-CCPCH
    config.SCCPCH.Enable = 'Off';
    config.SCCPCH.SlotFormat = 7;
    config.SCCPCH.SpreadingCode = 3; 
    config.SCCPCH.SecondaryScramblingCode = 0; 
    config.SCCPCH.TimingOffset = 0;
    config.SCCPCH.Power = 0;
    config.SCCPCH.TFCI = 0;
    config.SCCPCH.DataSource = 'CCTrCH'; 
    % Define CCTrCH containing PCH/FACH
    config.SCCPCH.CCTrCH.Name = '';
    config.SCCPCH.CCTrCH.DTXPosition = 'fixed';
    config.SCCPCH.CCTrCH.TrCH(1).Name = 'PCH';
    config.SCCPCH.CCTrCH.TrCH(1).CRC = '16';
    config.SCCPCH.CCTrCH.TrCH(1).CodingType = 'conv2';
    config.SCCPCH.CCTrCH.TrCH(1).RMA = 256;
    config.SCCPCH.CCTrCH.TrCH(1).TTI = 10; 
    config.SCCPCH.CCTrCH.TrCH(1).DataSource = 'PN9-ITU';
    config.SCCPCH.CCTrCH.TrCH(1).ActiveDynamicPart = 1; % Index to active dynamic part
    config.SCCPCH.CCTrCH.TrCH(1).DynamicPart(1) = struct('BlockSize',64,'BlockSetSize',64);   % 1x64 length block
    config.SCCPCH.CCTrCH.TrCH(2).Name = 'FACH';
    config.SCCPCH.CCTrCH.TrCH(2).CRC = '16';
    config.SCCPCH.CCTrCH.TrCH(2).CodingType = 'turbo';
    config.SCCPCH.CCTrCH.TrCH(2).RMA = 256;
    config.SCCPCH.CCTrCH.TrCH(2).TTI = 10; 
    config.SCCPCH.CCTrCH.TrCH(2).DataSource = 'PN9-ITU';
    config.SCCPCH.CCTrCH.TrCH(2).ActiveDynamicPart = 1; % Index to active dynamic part
    config.SCCPCH.CCTrCH.TrCH(2).DynamicPart(1) = struct('BlockSize',360,'BlockSetSize',360); % 1x360 length block
    
    % Define P-CPICH
    config.PCPICH.Enable = 'On'; 
    config.PCPICH.Power = 0; 
    
    % Define S-CPICH
    config.SCPICH.Enable = 'Off'; 
    config.SCPICH.SpreadingCode = 4;
    config.SCPICH.SecondaryScramblingCode = 0; 
    config.SCPICH.Power = 0; 
    
    % Define P-SCH
    config.PSCH.Enable = 'On'; 
    config.PSCH.Power = 0; 
    
    % Define S-SCH
    config.SSCH.Enable = 'On'; 
    config.SSCH.Power = 0; 
    
    % Define PICH 
    config.PICH.Enable = 'On';
    config.PICH.SpreadingCode = 16;
    config.PICH.TimingOffset = 0;
    config.PICH.Power = 0;
    config.PICH.DataSource = 'PagingData';
    config.PICH.Np = 144;
    
    % Define HSDPA
    config.HSDPA.Enable = 'On';
    config.HSDPA.CodeGroup = 5;
    config.HSDPA.CodeOffset = 1;
    config.HSDPA.Modulation = 'QPSK';
    config.HSDPA.VirtualBufferCapacity = 9600;
    config.HSDPA.InterTTIDistance = 3;
    config.HSDPA.NHARQProcesses = 2;                    
    config.HSDPA.XrvSequence = [0 2 5 6];
    config.HSDPA.UEId = 0;                    
    config.HSDPA.TransportBlockSizeId = 41; % TS25.321 Annex A + 9.2.3.1
    config.HSDPA.HSSCCHSpreadingCode = 9;
    config.HSDPA.SecondaryScramblingCode = 0;
    config.HSDPA.HSPDSCHPower = 0;
    config.HSDPA.HSSCCHPower = 0;
    config.HSDPA.DataSource = 'HSDSCH';
    % HS-DSCH config
    config.HSDPA.HSDSCH.BlockSize = 3202;
    config.HSDPA.HSDSCH.DataSource = 'PN9-ITU';
    
    % Define OCNS
    config.OCNS.Enable = 'On';
    config.OCNS.Power = 0;
    config.OCNS.OCNSType = 'RMC_16DPCH';
end

function config = getDLRMCConfig(config,rc)
    % Get the TrCHs from base configurations to modify
    TrCH(1) = config.DPCH.CCTrCH.TrCH(1);
    TrCH(2) = config.DPCH.CCTrCH.TrCH(2);
    switch upper(rc)
        case ('RMC0KBPS')
            % Build DTCH definition
            TrCH(1).Name = 'DTCH';
            TrCH(1).CRC = '16';
            TrCH(1).CodingType = 'conv3';
            TrCH(1).RMA = 256;
            TrCH(1).TTI = 20;
            % In the standard RMC definitions for 0kbps RMC, both the
            % BlockSize and BlockSetSize are specified to be 0, which
            % actually corresponds to a transmission of 0 transport block
            % (i.e no CRC). In the umts functions, 1 transport block of
            % size 0 can be signaled by setting only one of the parameters
            % (BlockSize, BlockSetSize) to 0.
            TrCH(1).DynamicPart(1) = struct('BlockSize',244,'BlockSetSize',0);   % 1x0 length block
            TrCH(1).DynamicPart(2) = struct('BlockSize',244,'BlockSetSize',244); % 1x244 length block
            % Build DCCH definition
            TrCH(2).Name = 'DCCH';
            TrCH(2).CRC = '12';
            TrCH(2).CodingType = 'conv3';
            TrCH(2).RMA = 256;
            TrCH(2).TTI = 40; 
            TrCH(2).DynamicPart(1) = struct('BlockSize',100,'BlockSetSize',100); % 1x100 length block
            
            config.DPCH.SlotFormat = 11;
            
        case ('RMC12.2KBPS')
            % Build DTCH definition
            TrCH(1).Name = 'DTCH';
            TrCH(1).CRC = '16';
            TrCH(1).CodingType = 'conv3';
            TrCH(1).RMA = 256;
            TrCH(1).TTI = 20;
            TrCH(1).DynamicPart(1) = struct('BlockSize',244,'BlockSetSize',244); % 1x244 length block
            % Build DCCH definition
            TrCH(2).Name = 'DCCH';
            TrCH(2).CRC = '12';
            TrCH(2).CodingType = 'conv3';
            TrCH(2).RMA = 256;
            TrCH(2).TTI = 40; 
            TrCH(2).DynamicPart(1) = struct('BlockSize',100,'BlockSetSize',100); % 1x100 length block
            
            config.DPCH.SlotFormat = 11;
            
        case ('RMC64KBPS')
            % Build DTCH definition
            TrCH(1).Name = 'DTCH';
            TrCH(1).CRC = '16';
            TrCH(1).CodingType = 'turbo';
            TrCH(1).RMA = 256;
            TrCH(1).TTI = 20;
            TrCH(1).DynamicPart(1) = struct('BlockSize',1280,'BlockSetSize',1280); % 1x1280 length block
            % Build DCCH definition
            TrCH(2).Name = 'DCCH';
            TrCH(2).CRC = '12';
            TrCH(2).CodingType = 'conv3';
            TrCH(2).RMA = 256;
            TrCH(2).TTI = 40; 
            TrCH(2).DynamicPart(1) = struct('BlockSize',100,'BlockSetSize',100);   % 1x100 length block
            
            config.DPCH.SlotFormat = 13;
            
       case ('RMC144KBPS')
            % Build DTCH definition
            TrCH(1).Name = 'DTCH';
            TrCH(1).CRC = '16';
            TrCH(1).CodingType = 'turbo';
            TrCH(1).RMA = 256;
            TrCH(1).TTI = 20;
            TrCH(1).DynamicPart(1) = struct('BlockSize',2880,'BlockSetSize',2880); % 1x2880 length block
            % Build DCCH definition
            TrCH(2).Name = 'DCCH';
            TrCH(2).CRC = '12';
            TrCH(2).CodingType = 'conv3';
            TrCH(2).RMA = 256;
            TrCH(2).TTI = 40; 
            TrCH(2).DynamicPart(1) = struct('BlockSize',100,'BlockSetSize',100);   % 1x100 length block
            
            config.DPCH.SlotFormat = 14;
            
        case ('RMC384KBPS')
            % Build DTCH definition
            TrCH(1).Name = 'DTCH';
            TrCH(1).CRC = '16';
            TrCH(1).CodingType = 'turbo';
            TrCH(1).RMA = 256;
            TrCH(1).TTI = 10;
            TrCH(1).DynamicPart(1) = struct('BlockSize',3840,'BlockSetSize',3840); % 1x3840 length block
            % Build DCCH definition
            TrCH(2).Name = 'DCCH';
            TrCH(2).CRC = '12';
            TrCH(2).CodingType = 'conv3';
            TrCH(2).RMA = 256;
            TrCH(2).TTI = 40; 
            TrCH(2).DynamicPart(1) = struct('BlockSize',100,'BlockSetSize',100);   % 1x100 length block
            
            config.DPCH.SlotFormat = 15;
            
        otherwise
          error('umts:error','Unsupported DL RMC specified')
    end
    % Finalize CCTrCH using the above
    config.DPCH.CCTrCH.TrCH(1) = TrCH(1);
    config.DPCH.CCTrCH.TrCH(2) = TrCH(2);
    
    config.HSDPA.Enable = 'Off'; % Turn off HSDPA channel
end

function config = getDLFRCConfig(config,frc,modulation)
   switch upper(frc)
        case 'H-SET1'
            if (isempty(modulation) || strcmpi(modulation,'QPSK')) 
                config.HSDPA.CodeGroup = 5;
                config.HSDPA.CodeOffset = 1;
                config.HSDPA.Modulation = 'QPSK';
                config.HSDPA.VirtualBufferCapacity = 9600;
                config.HSDPA.InterTTIDistance = 3;
                config.HSDPA.NHARQProcesses = 2;                    
                config.HSDPA.XrvSequence = [0 2 5 6];
                config.HSDPA.UEId = 0;                    
                config.HSDPA.TransportBlockSizeId = 41; %25.321 Annex A + 9.2.3.1
                config.HSDPA.HSSCCHSpreadingCode = 9;
                config.HSDPA.SecondaryScramblingCode = 0;
                config.HSDPA.HSPDSCHPower = 0;
                config.HSDPA.HSSCCHPower = 0;
                % HS-DSCH config
                config.HSDPA.HSDSCH.BlockSize = 3202;
             elseif (strcmpi(modulation,'16QAM')) 
                config.HSDPA.CodeGroup = 4;
                config.HSDPA.CodeOffset = 1;
                config.HSDPA.Modulation = '16QAM';
                config.HSDPA.VirtualBufferCapacity = 9600;
                config.HSDPA.InterTTIDistance = 3;
                config.HSDPA.NHARQProcesses = 2;                    
                config.HSDPA.XrvSequence = [6 2 1 5];
                config.HSDPA.UEId = 0;                    
                config.HSDPA.TransportBlockSizeId = 36; %25.321 Annex A + 9.2.3.1
                config.HSDPA.HSSCCHSpreadingCode = 9;
                config.HSDPA.SecondaryScramblingCode = 0;
                config.HSDPA.HSPDSCHPower = 0;
                config.HSDPA.HSSCCHPower = 0;
                % HS-DSCH config
                config.HSDPA.HSDSCH.BlockSize = 4664;
            else
                error('umts:error','For FRC H-Set1, modulation scheme must be ''QPSK'' or ''16QAM''');
            end
            % OCNS
            config.OCNS.OCNSType = 'H-Set_6DPCH';
            
        case 'H-SET2'
            if (isempty(modulation) || strcmpi(modulation,'QPSK')) 
                config.HSDPA.CodeGroup = 5;
                config.HSDPA.CodeOffset = 1;
                config.HSDPA.Modulation = 'QPSK';
                config.HSDPA.VirtualBufferCapacity = 9600;
                config.HSDPA.InterTTIDistance = 2;
                config.HSDPA.NHARQProcesses = 3;
                config.HSDPA.XrvSequence = [0 2 5 6];
                config.HSDPA.UEId = 0;                    
                config.HSDPA.TransportBlockSizeId = 41; %25.321 Annex A + 9.2.3.1
                config.HSDPA.HSSCCHSpreadingCode = 9;
                config.HSDPA.SecondaryScramblingCode = 0;
                config.HSDPA.HSPDSCHPower = 0;
                config.HSDPA.HSSCCHPower = 0;
                % HS-DSCH config
                config.HSDPA.HSDSCH.BlockSize = 3202;
            elseif (strcmpi(modulation,'16QAM')) 
                config.HSDPA.CodeGroup = 4;
                config.HSDPA.CodeOffset = 1;
                config.HSDPA.Modulation = '16QAM';
                config.HSDPA.VirtualBufferCapacity = 9600;
                config.HSDPA.InterTTIDistance = 2;
                config.HSDPA.NHARQProcesses = 3;
                config.HSDPA.XrvSequence = [6 2 1 5];
                config.HSDPA.UEId = 0;                    
                config.HSDPA.TransportBlockSizeId = 36; %25.321 Annex A + 9.2.3.1
                config.HSDPA.HSSCCHSpreadingCode = 9;
                config.HSDPA.SecondaryScramblingCode = 0;
                config.HSDPA.HSPDSCHPower = 0;
                config.HSDPA.HSSCCHPower = 0;
                % HS-DSCH config
                config.HSDPA.HSDSCH.BlockSize = 4664;
            else
                error('umts:error','For FRC H-Set2, modulation scheme must be ''QPSK'' or ''16QAM''');
            end
            % OCNS
            config.OCNS.OCNSType = 'H-Set_6DPCH';
            
        case 'H-SET3'
            if (isempty(modulation) || strcmpi(modulation,'QPSK')) 
                config.HSDPA.CodeGroup = 5;
                config.HSDPA.CodeOffset = 1;
                config.HSDPA.Modulation = 'QPSK';
                config.HSDPA.VirtualBufferCapacity = 9600;
                config.HSDPA.InterTTIDistance = 1;
                config.HSDPA.NHARQProcesses = 6;
                config.HSDPA.XrvSequence = [0 2 5 6];
                config.HSDPA.UEId = 0;                    
                config.HSDPA.TransportBlockSizeId = 41; %25.321 Annex A + 9.2.3.1
                config.HSDPA.HSSCCHSpreadingCode = 9;
                config.HSDPA.SecondaryScramblingCode = 0;
                config.HSDPA.HSPDSCHPower = 0;
                config.HSDPA.HSSCCHPower = 0;
                % HS-DSCH config
                config.HSDPA.HSDSCH.BlockSize = 3202;
            elseif (strcmpi(modulation,'16QAM')) 
                config.HSDPA.CodeGroup = 4;
                config.HSDPA.CodeOffset = 1;
                config.HSDPA.Modulation = '16QAM';
                config.HSDPA.VirtualBufferCapacity = 9600;
                config.HSDPA.InterTTIDistance = 1;
                config.HSDPA.NHARQProcesses = 6;
                config.HSDPA.XrvSequence = [6 2 1 5];
                config.HSDPA.UEId = 0;                    
                config.HSDPA.TransportBlockSizeId = 36; %25.321 Annex A + 9.2.3.1
                config.HSDPA.HSSCCHSpreadingCode = 9;
                config.HSDPA.SecondaryScramblingCode = 0;
                config.HSDPA.HSPDSCHPower = 0;
                config.HSDPA.HSSCCHPower = 0;
                % HS-DSCH config
                config.HSDPA.HSDSCH.BlockSize = 4664;
            else
                error('umts:error','For FRC H-Set3, modulation scheme must be ''QPSK'' or ''16QAM''');
            end
            % OCNS
            config.OCNS.OCNSType = 'H-Set_6DPCH';
            
        case 'H-SET4'
            if (isempty(modulation) || strcmpi(modulation,'QPSK')) 
                config.HSDPA.CodeGroup = 5;
                config.HSDPA.CodeOffset = 1;
                config.HSDPA.Modulation = 'QPSK';
                config.HSDPA.VirtualBufferCapacity = 7200;
                config.HSDPA.InterTTIDistance = 2;
                config.HSDPA.NHARQProcesses = 2;
                config.HSDPA.XrvSequence = [0 2 5 6];
                config.HSDPA.UEId = 0;
                config.HSDPA.TransportBlockSizeId = 41; %25.321 Annex A + 9.2.3.1
                config.HSDPA.HSSCCHSpreadingCode = 9;
                config.HSDPA.SecondaryScramblingCode = 0;
                config.HSDPA.HSPDSCHPower = 0;
                config.HSDPA.HSSCCHPower = 0;
                % HS-DSCH config
                config.HSDPA.HSDSCH.BlockSize = 3202;
                % OCNS
                config.OCNS.OCNSType = 'H-Set_6DPCH';
            else
                error('umts:error','For FRC H-Set4, modulation scheme must be ''QPSK''');
            end

        case 'H-SET5'
            if (isempty(modulation) || strcmpi(modulation,'QPSK')) 
                config.HSDPA.CodeGroup = 5;
                config.HSDPA.CodeOffset = 1;
                config.HSDPA.Modulation = 'QPSK';
                config.HSDPA.VirtualBufferCapacity = 9600;
                config.HSDPA.InterTTIDistance = 1;
                config.HSDPA.NHARQProcesses = 3;
                config.HSDPA.XrvSequence = [0 2 5 6];
                config.HSDPA.UEId = 0;
                config.HSDPA.TransportBlockSizeId = 41; %25.321 Annex A + 9.2.3.1
                config.HSDPA.HSSCCHSpreadingCode = 9;
                config.HSDPA.SecondaryScramblingCode = 0;
                config.HSDPA.HSPDSCHPower = 0;
                config.HSDPA.HSSCCHPower = 0;
                % HS-DSCH config
                config.HSDPA.HSDSCH.BlockSize = 3202;
                % OCNS
                config.OCNS.OCNSType = 'H-Set_6DPCH';
            else
                error('umts:error','For FRC H-Set5, modulation scheme must be ''QPSK''');
            end

        case 'H-SET6'
            if (isempty(modulation) || strcmpi(modulation,'QPSK')) 
                config.HSDPA.CodeGroup = 10;
                config.HSDPA.CodeOffset = 1;
                config.HSDPA.Modulation = 'QPSK';
                config.HSDPA.VirtualBufferCapacity = 19200;
                config.HSDPA.InterTTIDistance = 1;
                config.HSDPA.NHARQProcesses = 6;
                config.HSDPA.XrvSequence = [0 2 5 6];
                config.HSDPA.UEId = 0;                    
                config.HSDPA.TransportBlockSizeId = 41; %25.321 Annex A + 9.2.3.1
                config.HSDPA.HSSCCHSpreadingCode = 9;
                config.HSDPA.SecondaryScramblingCode = 0;
                config.HSDPA.HSPDSCHPower = 0;
                config.HSDPA.HSSCCHPower = 0;
                % HS-DSCH config
                config.HSDPA.HSDSCH.BlockSize = 6438;
            elseif (strcmpi(modulation,'16QAM')) 
                config.HSDPA.CodeGroup = 8;
                config.HSDPA.CodeOffset = 1;
                config.HSDPA.Modulation = '16QAM';
                config.HSDPA.VirtualBufferCapacity = 19200;
                config.HSDPA.InterTTIDistance = 1;
                config.HSDPA.NHARQProcesses = 6;
                config.HSDPA.XrvSequence = [6 2 1 5];
                config.HSDPA.UEId = 0;                    
                config.HSDPA.TransportBlockSizeId = 36; %25.321 Annex A + 9.2.3.1
                config.HSDPA.HSSCCHSpreadingCode = 9;
                config.HSDPA.SecondaryScramblingCode = 0;
                config.HSDPA.HSPDSCHPower = 0;
                config.HSDPA.HSSCCHPower = 0;
                % HS-DSCH config
                config.HSDPA.HSDSCH.BlockSize = 9377;
            else
                error('umts:error','For FRC H-Set6, modulation scheme must be ''QPSK'' or ''16QAM''');
            end
            % OCNS
            config.OCNS.OCNSType = 'H-Set_6DPCH';
            
        case 'H-SET7'
            if (isempty(modulation) || strcmpi(modulation,'QPSK')) 
                config.HSDPA.CodeGroup = 1;
                config.HSDPA.CodeOffset = 1;
                config.HSDPA.Modulation = 'QPSK';
                config.HSDPA.VirtualBufferCapacity = 2400;
                config.HSDPA.InterTTIDistance = 8;
                config.HSDPA.NHARQProcesses = 1;
                config.HSDPA.XrvSequence = [0 2 5 6];
                config.HSDPA.UEId = 0;
                config.HSDPA.TransportBlockSizeId = 39; %25.321 Annex A + 9.2.3.1
                config.HSDPA.HSSCCHSpreadingCode = 9;
                config.HSDPA.SecondaryScramblingCode = 0;
                config.HSDPA.HSPDSCHPower = 0;
                config.HSDPA.HSSCCHPower = 0;
                % HS-DSCH config
                config.HSDPA.HSDSCH.BlockSize = 605;
            else
                error('umts:error','For FRC H-Set7, modulation scheme must be ''QPSK''');
            end

       case 'H-SET8'
        if (isempty(modulation) || strcmpi(modulation,'64QAM')) 
            config.HSDPA.CodeGroup = 15;
            config.HSDPA.CodeOffset = 1;
            config.HSDPA.Modulation = '64QAM';
            config.HSDPA.VirtualBufferCapacity = 43200;
            config.HSDPA.InterTTIDistance = 1;
            config.HSDPA.NHARQProcesses = 6;
            config.HSDPA.XrvSequence = [6 2 1 5];
            config.HSDPA.UEId = 0;
            config.HSDPA.TransportBlockSizeId = 36; %25.321 Annex A + 9.2.3.1
            config.HSDPA.HSSCCHSpreadingCode = 9;
            config.HSDPA.SecondaryScramblingCode = 0;
            config.HSDPA.HSPDSCHPower = 0;
            config.HSDPA.HSSCCHPower = 0;
            % HS-DSCH config
            config.HSDPA.HSDSCH.BlockSize = 26504;
            % OCNS
            config.OCNS.OCNSType = 'H-Set_4DPCH';
        else
            error('umts:error','For FRC H-Set8, modulation scheme must be ''64QAM''');
        end
        %case 'H-Set9' - Multiple transport blocks - Not supported

        case 'H-SET10'
            if (isempty(modulation) || strcmpi(modulation,'QPSK')) 
                config.HSDPA.CodeGroup = 15;
                config.HSDPA.CodeOffset = 1;
                config.HSDPA.Modulation = 'QPSK';
                config.HSDPA.VirtualBufferCapacity = 28800;
                config.HSDPA.InterTTIDistance = 1;
                config.HSDPA.NHARQProcesses = 6;
                config.HSDPA.XrvSequence = [0 2 5 6];
                config.HSDPA.UEId = 0;                    
                config.HSDPA.TransportBlockSizeId = 42; %25.321 Annex A + 9.2.3.1
                config.HSDPA.HSSCCHSpreadingCode = 9;
                config.HSDPA.SecondaryScramblingCode = 0;
                config.HSDPA.HSPDSCHPower = 0;
                config.HSDPA.HSSCCHPower = 0;
                % HS-DSCH config
                config.HSDPA.HSDSCH.BlockSize = 9719;
            elseif (strcmpi(modulation,'16QAM')) 
                config.HSDPA.CodeGroup = 15;
                config.HSDPA.CodeOffset = 1;
                config.HSDPA.Modulation = '16QAM';
                config.HSDPA.VirtualBufferCapacity = 28800;
                config.HSDPA.InterTTIDistance = 1;
                config.HSDPA.NHARQProcesses = 6;
                config.HSDPA.XrvSequence = [6 2 1 5];
                config.HSDPA.UEId = 0;                    
                config.HSDPA.TransportBlockSizeId = 36; %25.321 Annex A + 9.2.3.1
                config.HSDPA.HSSCCHSpreadingCode = 9;
                config.HSDPA.SecondaryScramblingCode = 0;
                config.HSDPA.HSPDSCHPower = 0;
                config.HSDPA.HSSCCHPower = 0;
                % HS-DSCH config
                config.HSDPA.HSDSCH.BlockSize = 17548;
            else
                error('umts:error','For FRC H-Set10, modulation scheme must be ''QPSK'' or ''16QAM''');
            end  
            % OCNS
            config.OCNS.OCNSType = 'H-Set_4DPCH';
            
        %case 'H-Set11' - Multiple transport blocks - Not supported

        case 'H-SET12'
            if (isempty(modulation) || strcmpi(modulation,'QPSK'))
                config.HSDPA.CodeGroup = 1;
                config.HSDPA.CodeOffset = 1;
                config.HSDPA.Modulation = 'QPSK';
                config.HSDPA.VirtualBufferCapacity = 3200;
                config.HSDPA.InterTTIDistance = 1;
                config.HSDPA.NHARQProcesses = 6;
                config.HSDPA.XrvSequence = [0 2 5 6];
                config.HSDPA.UEId = 0;                    
                config.HSDPA.TransportBlockSizeId = 0; %25.321 Annex A + 9.2.3.1
                config.HSDPA.HSSCCHSpreadingCode = 9;
                config.HSDPA.SecondaryScramblingCode = 0;
                config.HSDPA.HSPDSCHPower = 0;
                config.HSDPA.HSSCCHPower = 0;
                % HS-DSCH config
                config.HSDPA.HSDSCH.BlockSize = 120;
            else
                error('umts:error','For FRC H-Set12, modulation scheme must be ''QPSK''');
            end
        otherwise
            error('umts:error','Unsupported DL H-Set specified');

    end
end


function config = getDLTMConfig(config,rc)
    config = getGeneralTMSettings(config);
    switch upper(rc)
        case 'TM1_4DPCH'
            config.OCNS.OCNSType = 'TM1_4DPCH';
        case 'TM1_8DPCH'
            config.OCNS.OCNSType = 'TM1_8DPCH'; 
        case 'TM1_16DPCH'
            config.OCNS.OCNSType = 'TM1_16DPCH';   
        case 'TM1_32DPCH'
            config.OCNS.OCNSType = 'TM1_32DPCH';     
        case 'TM1_64DPCH'
            config.OCNS.OCNSType = 'TM1_64DPCH'; 
        case 'TM2_3DPCH'
            config.SCCPCH.Enable = 'On';
            config.SCCPCH.Power = -13;
            config.PICH.Power = -13;
            config.OCNS.OCNSType = 'TM2_3DPCH'; 
        case 'TM3_4DPCH'
            config.PCCPCH.Power = -8;
            config.SCCPCH.Power = -16;
            config.PCPICH.Power = -8;
            config.PSCH.Power = -8;
            config.SSCH.Power = -8;
            config.PICH.Power = -16;
            config.OCNS.OCNSType = 'TM3_4DPCH';
        case 'TM3_8DPCH'
            config.PCCPCH.Power = -8;
            config.SCCPCH.Power = -16;
            config.PCPICH.Power = -8;
            config.PSCH.Power = -8;
            config.SSCH.Power = -8;
            config.PICH.Power = -16;
            config.OCNS.OCNSType = 'TM3_8DPCH'; 
        case 'TM3_16DPCH'
            config.PCCPCH.Power = -9;
            config.SCCPCH.Power = -13;
            config.PCPICH.Power = -9;
            config.PSCH.Power = -9;
            config.SSCH.Power = -9;
            config.PICH.Power = -13;
            config.OCNS.OCNSType = 'TM3_16DPCH';   
        case 'TM3_32DPCH'
            config.PCCPCH.Power = -11;
            config.SCCPCH.Power = -18;
            config.PCPICH.Power = -11;
            config.PSCH.Power = -11;
            config.SSCH.Power = -11;
            config.PICH.Power = -18;
            config.OCNS.OCNSType = 'TM3_32DPCH';  
        case 'TM4'
            config.PCCPCH.Power = 0;
            config.SCCPCH.Enable = 'Off';
            config.PCPICH.Enable = 'Off';
            config.PSCH.Power = 0;
            config.SSCH.Power = 0;
            config.PICH.Enable = 'Off';
            config.OCNS.Enable = 'Off';     
        case 'TM5_4DPCH_4HSPDSCH'
            config = getHSTestModelConfig(config);
            config.OCNS.OCNSType = 'TM5_4DPCH_4HSPDSCH';
        case 'TM5_6DPCH_2HSPDSCH'
            config = getHSTestModelConfig(config);
            config.OCNS.OCNSType = 'TM5_6DPCH_2HSPDSCH';
        case 'TM5_14DPCH_4HSPDSCH'
            config = getHSTestModelConfig(config);
            config.OCNS.OCNSType = 'TM5_14DPCH_4HSPDSCH';
        case 'TM5_30DPCH_8HSPDSCH'
            config = getHSTestModelConfig(config);
            config.OCNS.OCNSType = 'TM5_30DPCH_8HSPDSCH';
        case 'TM6_4DPCH_4HSPDSCH'
            config = getHSTestModelConfig(config);
            config.OCNS.OCNSType = 'TM6_4DPCH_4HSPDSCH';
        case 'TM6_30DPCH_8HSPDSCH'
            config = getHSTestModelConfig(config);
            config.OCNS.OCNSType = 'TM6_30DPCH_8HSPDSCH';
        otherwise    
            error('umts:error','Unsupported DL Test Model specified');
    end
    
end

function config = getHSTestModelConfig(config)
    % Set the power levels for non HS channels
    config.PCCPCH.Power = -11;
    config.SCCPCH.Power = -19;
    config.PCPICH.Power = -11;
    config.PSCH.Power = -11;
    config.SSCH.Power = -11;
    config.PICH.Power = -19;
    config.HSDPA.CodeGroup = 2;
    config.HSDPA.CodeOffset = 4;
    config.HSDPA.Modulation = '16QAM';
    config.HSDPA.VirtualBufferCapacity = 9600;
    config.HSDPA.InterTTIDistance = 1;
    config.HSDPA.NHARQProcesses = 1;
    config.HSDPA.XrvSequence = [6 2 1 5];
    config.HSDPA.UEId = 0;                    
    config.HSDPA.TransportBlockSizeId = 36; %25.321 Annex A + 9.2.3.1
    config.HSDPA.HSSCCHSpreadingCode = 9;
    config.HSDPA.SecondaryScramblingCode = 0;
    config.HSDPA.DataSource = 'PN9-ITU';
    config.HSDPA.Enable = 'Off';
    config.HSDPA.HSPDSCHPower = 0;
    config.HSDPA.HSSCCHPower = 0;
    % HS-DSCH config
    config.HSDPA.HSDSCH.BlockSize = 4664;
    config.HSDPA.HSDSCH.DataSource = 'PN9-ITU';
end

function config = getGeneralTMSettings(config)
    config.HSDPA.Enable = 'Off'; % Turn off HSDPA channel
    config.DPCH.Enable = 'Off';
    config.PCCPCH.DataSource = {'PN9-ITU',1};
    config.PCCPCH.Power = -10;
    config.SCCPCH.Enable = 'On';
    config.SCCPCH.SlotFormat = 3;
    config.SCCPCH.DataSource = {'PN9-ITU',config.SCCPCH.SpreadingCode};
    config.SCCPCH.Power = -18;
    config.PCPICH.Power = -10;
    config.PSCH.Power = -10;
    config.SSCH.Power = -10;
    config.PICH.Np = 18;
    config.PICH.Power = -18;
    config.PICH.TimingOffset = 120;
end


