function waveformStruct = cdma2000ForwardReferenceChannels(varargin)
%cdma2000ForwardReferenceChannels Preset forward cdma2000 waveforms
%   WAVEFORMSTRUCT = cdma2000ForwardReferenceChannels(WAVEFORMID) returns a
%   configuration structure WAVEFORMSTRUCT that can be passed to
%   cdma2000ForwardWaveformGenerator in order to generate the corresponding
%   waveform. WAVEFORMID can take one of the following string values:
%
%   - 'F-PICH-ONLY' - Forward Pilot Channel only.
%
%   - Forward Control Channel preset waveforms; 'CONTROL-CCCHDataRate(bps)-CCCHFrameLength(ms)-BCCHDataRate(bps)' format:
%     'CONTROL-9600-20-4800',  'CONTROL-9600-20-9600',  'CONTROL-9600-20-19200',
%     'CONTROL-19200-10-4800', 'CONTROL-19200-10-9600', 'CONTROL-19200-10-19200',
%     'CONTROL-19200-20-4800', 'CONTROL-19200-20-9600', 'CONTROL-19200-20-19200',
%     'CONTROL-38400-5-4800',  'CONTROL-38400-5-9600',  'CONTROL-38400-5-19200',
%     'CONTROL-38400-10-4800', 'CONTROL-38400-10-9600', 'CONTROL-38400-10-19200',
%     'CONTROL-38400-20-4800', 'CONTROL-38400-20-9600', 'CONTROL-38400-20-19200'
%
%   - Forward Traffic Channel preset waveforms; 'TRAFFIC-RadioConfiguration-FCHDataRate(bps)' format: 
%     For X = 1:          'TRAFFIC-RCX-1200', 'TRAFFIC-RCX-2400', 'TRAFFIC-RCX-4800', 'TRAFFIC-RCX-9600' 
%     For X = 2,5,8 or 9: 'TRAFFIC-RCX-1800', 'TRAFFIC-RCX-3600', 'TRAFFIC-RCX-7200', 'TRAFFIC-RCX-14400'
%     For X = 3,4,6 or 7: 'TRAFFIC-RCX-1500', 'TRAFFIC-RCX-2700', 'TRAFFIC-RCX-4800', 'TRAFFIC-RCX-9600'
%
%   - Models for testing the base station transmitter - see Sec. 6.5.2 in C.S0010-E v2.0:
%     'BSTM-RC1', 'BSTM-RC2', 'BSTM-RC3', 'BSTM-RC4', 'BSTM-RC5'
%     'BSTM-RC6', 'BSTM-RC7', 'BSTM-RC8', 'BSTM-RC9'
%
%   - Return all channels supported for the specified radio configuration:
%     'ALL-RC1', 'ALL-RC2', 'ALL-RC3', 'ALL-RC4', 'ALL-RC5', 'ALL-RC6',
%     'ALL-RC7', 'ALL-RC8', 'ALL-RC9'
%
%   WAVEFORMSTRUCT = cdma2000ForwardReferenceChannels(WAVEFORMID, NUMCHIPS)
%   behaves as cdma2000ForwardReferenceChannels(WAVEFORMID), but it also
%   specifies the number of chips. If omitted, NUMCHIPS defaults to 1000.
%
%   WAVEFORMSTRUCT = cdma2000ForwardReferenceChannels('BSTM-RC*', NUMCHIPS, POWERBUDGET, M)
%   can be used for the 'BSTM-RC*' waveform IDs. POWERBUDGET is the total
%   power (in dBW) that is allocated to the individual channels. M is the
%   number of traffic channels. If omitted, POWERBUDGET defaults to 0 dBW
%   and M defaults to 6.
%
%   WAVEFORMSTRUCT = cdma2000ForwardReferenceChannels('TRAFFIC*', NUMCHIPS, F-SCH-SPEC) 
%   also determines the data rate and frame length of the Forward Supplemental
%   Channel (F-SCH) for RC3-RC9 using a 'F-SCH-DataRate(bps)-FrameLength(ms)'
%   string format. If omitted, F-SCH-SPEC defaults to the ID of the lowest
%   F-SCH data rate allowable for a 20 ms frame length under the specified
%   radio configuration.
%
%   Example 1:
%      config   = cdma2000ForwardReferenceChannels('ALL-RC2');
%      waveform = cdma2000ForwardWaveformGenerator(config)
%
%   Example 2:
%      config   = cdma2000ForwardReferenceChannels('TRAFFIC-RC3-1500', 1000, 'F-SCH-4800-20');
%      waveform = cdma2000ForwardWaveformGenerator(config)
%
%   Example 3:
%      config   = cdma2000ForwardReferenceChannels('BSTM-RC1', 1000, -10, 37);
%      waveform = cdma2000ForwardWaveformGenerator(config)
%
%   Example 4:
%      config   = cdma2000ForwardReferenceChannels('CONTROL-19200-10-4800');
%      waveform = cdma2000ForwardWaveformGenerator(config)
%
%   See also cdma2000ForwardWaveformGenerator, cdma2000ReverseReferenceChannels, 
%            evdoForwardReferenceChannels, evdoReverseReferenceChannels

%   Copyright 2015-2016 The MathWorks, Inc.

    % default values:
    if nargin > 0
        [varargin{:}] = convertStringsToChars(varargin{:});
    end
    
    waveformID  = 'ALL-RC3';
    numChips    = 1000;
    power       = 0;
    M           = 6;

    if nargin >= 1
        % 1st argument validation:
        validateattributes(varargin{1}, {'char'}, {'row'}, 'cdma2000ForwardReferenceChannels', 'waveformID');
        waveformID = varargin{1};
        
        if nargin >= 2 %numChips specified. 
            % 2nd argument validation:
            validateattributes(varargin{2}, {'numeric'}, {'scalar', 'real', 'integer', 'positive'}, 'cdma2000ForwardReferenceChannels', 'numChips');
            numChips = varargin{2};

            if nargin >= 3

                % 3rd argument validation:
                if strncmpi(waveformID, 'TRAFFIC', 7)
                    % 3rd argument should be F-SCH specification
                    validateattributes(varargin{3}, {'char'}, {'row'}, 'cdma2000ForwardReferenceChannels', 'F-SCH specification');
                    supSpec = varargin{3};
                elseif strncmpi(waveformID, 'BSTM', 4)
                    % 3rd argument should be power
                    validateattributes(varargin{3}, {'numeric'}, {'scalar', 'real', 'integer'}, 'cdma2000ForwardReferenceChannels', 'power');
                    power = varargin{3};
                else
                    id = 'comm:cdma2000evdoParameterGeneration:Fcdma2000ThirdInputNotAllowed';
                    error(id, getString( message(id, waveformID) ) );
                end

                % 4 or more arguments:
                if nargin == 4
                    if ~strncmpi(waveformID, 'BSTM', 4)
                        id = 'comm:cdma2000evdoParameterGeneration:FourthInputNotAllowed';
                        error(id, getString( message(id, waveformID) ) );
                    end

                    % 4th argument (M) validation:
                    validateattributes(varargin{4}, {'numeric'}, {'scalar', 'real', 'integer', 'positive'}, 'cdma2000ForwardReferenceChannels', 'M');
                    M = varargin{4};
                elseif nargin > 4
                    id = 'comm:cdma2000evdoParameterGeneration:TooManyInputArgs';
                    error(id, getString( message(id, 'cdma2000ForwardReferenceChannels', 4) ) );
                end
            end
        end
    end
    
    % F-PICH-ONLY
    if any(strcmpi(waveformID, {'F-PICH-ONLY', 'FPICH_ONLY', 'FPICH-ONLY', 'F-PICH_ONLY', 'FPICHONLY'}))
        
        % return a waveform containing the pilot channel only
        waveformStruct = createPilotOnly(numChips);
        
    % CONTROL-*    
    elseif strncmpi(waveformID, 'CONTROL', 7)
        
        [dataRate1, frameLength1, dataRate2] = parseWaveformID(waveformID, 3); % parse
        
        validateFcontrolSpecification(dataRate1, frameLength1, dataRate2); % validate
        
        waveformStruct = createFcontrolConfiguration(dataRate1, frameLength1, dataRate2, numChips); % create
        
    % TRAFFIC-*
    elseif strncmpi(waveformID, 'TRAFFIC', 7)
        
        [RC, dataRate] = parseWaveformID(waveformID, 2); % parse
        
        % account for F-SCH specification, either from user or default
        if nargin == 3
            [dataRateSup, frameLengthSup] = parseWaveformID(supSpec, 2);
        else
            [dataRateSup, frameLengthSup] = getDefaultSupSpec(RC);
        end
        
        % validate:
        validateRadioConfiguration(RC);
        validateFFCHdataRate(RC, dataRate);
        if RC >= 3 && RC <= 9 % F-SCH only defined for RC3-RC9
            validateFSCHConfiguration(RC, dataRateSup, frameLengthSup);
        else % RC == 1 || RC == 2
           if nargin == 3
               % F-SCH specification has been provided, but it is not
               % relevant under this radio configuration
               warningID = 'comm:cdma2000evdoParameterGeneration:NotRelevantFSCHspec';
               warning(warningID, getString( message(warningID, RC) ) );
           end
        end
        
        % create:
        waveformStruct = createR_Traffic_Configuration(RC, dataRate, dataRateSup, frameLengthSup, numChips);
        
    % BSTM-RC-*
    elseif strncmpi(waveformID, 'BSTM', 4)
    
        % create waveform widely used for testing the mobile station as a
        % transmitter - see Chapter 4 in C.S0010-Ev2.0:
        % http://www.3gpp2.org/Public_html/specs/C.S0010-E_v2.0_20140321.pdf
        
        RC = parseWaveformID(waveformID, 1); % parse
        
        waveformStruct = createTXtestWaveform(RC, power, M, numChips);
        
    % ALL-*
    elseif strncmpi(waveformID, 'ALL', 3)
        
        rc = parseWaveformID(waveformID, 1);
        
        % validate radio configuration:
        validateRadioConfiguration(rc);
        
        % get all channels supported for that radio configuration:
        waveformStruct = getAllChannels(rc, numChips);
    
    else % Invalid input ID, message points to all acceptable IDs
        invalidIDerror(waveformID);
    end
end

function waveformStruct = createPilotOnly(numChips)
    
    % top-level waveform creation:    
    waveformStruct = createTopLevelWaveform(1, numChips); % force SR1
    
    % Forward Pilot Channel (F-PICH)
    fpich.Enable = 'On';
    fpich.Power  = 0;
    waveformStruct.FPICH = fpich;
end

function waveformStruct = createTopLevelWaveform(RC, numChips)
        
    % top-level waveform creation:
    if RC < 6 % RC1 - RC5
        waveformStruct.SpreadingRate = 'SR1';
    else % RC6 - RC9
        waveformStruct.SpreadingRate = 'SR3';
    end        
    
    waveformStruct.Diversity            = 'NTD';
    waveformStruct.QOF                  = 'QOF1';
    waveformStruct.PNOffset             = 0;
    waveformStruct.LongCodeState        = 0;
    waveformStruct.PowerNormalization   = 'Off';
    
    % Filtering and modulation parameters:
    waveformStruct.OversamplingRatio    = 4;
    waveformStruct.FilterType           = 'cdma2000Long';
    waveformStruct.InvertQ              = 'Off';
    waveformStruct.EnableModulation     = 'Off';
    waveformStruct.ModulationFrequency  = 0;
    
    waveformStruct.NumChips = numChips;
end

function [number1, number2, number3] = parseWaveformID(waveformID, numParsings)

    % parses NUMPARSINGS different numbers from the waveform ID

    delimiter = '-';
    
    % get first substring until delimiter ('-')
    [~, remain] = strtok(waveformID, delimiter);
    
    % discard the first token which does not contain data, i.e., CONTROL, TRAFFIC, BSTM, ALL, F-
    
    % get second substring until next delimiter ('-')
    [token, remain] = strtok(remain, delimiter);
    if strcmpi(token, 'SCH')
        [token, remain] = strtok(remain, delimiter); % discard SCH
    end
    
    if strncmpi(token, 'RC', 2)
        token(1:2) = []; % remove 'RC' from e.g., RC3, and only keep the number
    end
    
    % parse the first number:
    if isempty(token) || isnan(str2double(token))
        % Invalid input ID, hint all that are acceptable:
        invalidIDerror(waveformID);
    end
    
    number1 = str2double(token);
            
    if numParsings >= 2
        % now parse the 2nd number (always number of slots), so get third substring
        [token, remain] = strtok(remain, delimiter);

        if isempty(token) || isnan(str2double(token))
            invalidIDerror(waveformID);
        end

        number2 = str2double(token);

        if (numParsings == 2 && ~isempty(remain)) || (numParsings == 3 && isempty(remain))
            invalidIDerror(waveformID);
        end
        
        if numParsings == 3                        
            [token, ~] = strtok(remain, delimiter);

            if isnan(str2double(token))
                invalidIDerror(waveformID);
            end
            number3 = str2double(token);            
        end
    end
end

function validateFcontrolSpecification(dataRate1, frameLength1, dataRate2)

    % combinations allowed by the standard, see Tables 3.1.3.1.3 - 1&2 in C.S0002-Ev3.0:
    % http://www.3gpp2.org/Public_html/specs/C.S0002-F v2.0_20140519.pdf
    %                             DataRate      FrameLength
    validFCCCHCombinations = [      9600            20; ...
                                    19200           10; ...
                                    19200           20; ...
                                    38400           5;  ...
                                    38400           10;  ...
                                    38400           20 ];
    
    waveformID = ['F-CONTROL-' num2str(dataRate1) '-' num2str(frameLength1) '-' num2str(dataRate2)];
    if ~any( ismember(validFCCCHCombinations, [dataRate1 frameLength1], 'rows') )
        invalidIDerror(waveformID);
    end
    
    validBCCHrates = [4800 9600 19200];
    
    if ~any( ismember(validBCCHrates, dataRate2) )
        invalidIDerror(waveformID);
    end
end

function waveformStruct = createFcontrolConfiguration(dataRate1, frameLength1, dataRate2, numChips)

    % top-level waveform creation:    
    waveformStruct = createTopLevelWaveform(1, numChips); % force SR1
    
    % Forward Pilot Channel (F-PICH)
    fpich.Enable        = 'On';
    fpich.Power         = 0;
    waveformStruct.FPICH = fpich;
    
    % Forward Paging Channel (F-PCH)
    fpch.Enable         = 'On';
    fpch.Power          = 0;
    fpch.LongCodeMask   = 0;
    % F-PCH supports both 9600 and 4800, defaulting to 9600
    fpch.DataRate       = 4800;
    fpch.EnableCoding   = 'On';
    fpch.DataSource     = {'PN9', 1};
    fpch.WalshCode      = 1;
    waveformStruct.FPCH = fpch;
    
    % Forward Common Control Channel (F-CCCH)
    fccch.Enable         = 'On';
    fccch.Power          = 0;
    fccch.LongCodeMask   = 0;
    fccch.DataRate       = dataRate1;
    fccch.FrameLength    = frameLength1;
    fccch.EnableCoding   = 'On';
    fccch.DataSource     = {'PN9', 1};
    fccch.WalshCode      = 2;
    fccch.CodingType     = 'conv';
    waveformStruct.FCCCH = fccch;
    
    % Forward Broadcast Control Channel (F-BCCH)
    fbcch.Enable         = 'On';
    fbcch.Power          = 0;
    fbcch.LongCodeMask   = 0;
    fbcch.DataRate       = dataRate2;
    fbcch.EnableCoding   = 'On';
    fbcch.DataSource     = {'PN9', 1};
    fbcch.WalshCode      = 3;
    fbcch.CodingType     = 'conv';
    waveformStruct.FBCCH = fbcch;
end

function  [dataRateSup, frameLengthSup] = getDefaultSupSpec(RC)

    % if no F-SCH ID is specified, then the default configuration
    % corresponds to the lowest allowable data rate for 20 ms frame length
    % in the Fundamental Supplemental Channel (F-SCH)
    frameLengthSup = 20;
    
    switch RC
        case 1
            % in this case F-SCCH is used, not F-SCH
            dataRateSup = 9600;
        case 2
            % in this case F-SCCH is used, not F-SCH
            dataRateSup = 14400;
        case {3, 4, 6, 7}
            dataRateSup = 1500;
        case {5, 8, 9}
            dataRateSup = 1800;
        otherwise
            dataRateSup = []; % validateRadioConfiguration will error out
    end
end

function validateRadioConfiguration(RC)
    % the standard specifies 12 RCs, but the waveform generation functions
    % only support RC 1-9
    supportedRCs = 1:9;
    
    if ~any(ismember(supportedRCs, RC))
        id = 'comm:cdma2000evdoParameterGeneration:FUnsupportedRC';
        error(id, getString(message(id)));
    end
end

function validateFFCHdataRate(RC, dataRate)

    % F-FCH rates allowed by the standard, see Tables 3.1.3.1.3 - 1&2 in C.S0002-Ev3.0:
    % http://www.3gpp2.org/Public_html/specs/C.S0002-F v2.0_20140519.pdf
    
    if RC == 1
        validFCHRates = [1200, 2400, 4800, 9600];
    elseif RC == 2 || RC == 5 || RC == 8 || RC == 9
        validFCHRates = [1800, 3600, 7200, 14400];
    elseif RC == 3 || RC == 4 || RC == 6 || RC == 7
        validFCHRates = [1500, 2700, 4800, 9600];
    end
    
    if ~any(ismember(validFCHRates, dataRate))
        waveformID = ['TRAFFIC-RC' num2str(RC) '-' num2str(dataRate)];
        invalidIDerror(waveformID);
    end
end

function validateFSCHConfiguration(RC, dataRateSup, frameLengthSup)
    
    % combinations allowed by the standard for the Forward Supplemental
    % Channel (F-SCH), see Tables 3.1.3.1.3 - 2&4 in C.S0002-Ev3.0:
    % http://www.3gpp2.org/Public_html/specs/C.S0002-F v2.0_20140519.pdf

    if RC == 3 || RC == 4 || RC ==6 || RC == 7
        %                     DataRate  FrameLength
        validCombinations = [   1500        20; ...
                                2700        20; ...
                                4800        20; ...
                                9600        20; ...
                                19200       20; ...
                                38400       20; ...
                                76800       20; ...
                                153600      20; ...
                                1350        40; ...
                                2400        40; ...
                                4800        40; ...
                                9600        40; ...
                                19200       40; ...
                                38400       40; ...
                                76800       40; ...
                                1200        80; ...
                                2400        80; ...
                                4800        80; ...
                                9600        80; ...
                                19200       80; ...
                                38400       80 ];
                            
        if RC == 4 || RC ==6 || RC == 7
            % some additional combinations also apply
            validCombinations = [validCombinations;
                                307200      20; ...
                                153600      40; ...
                                76800       80];
        end
        
        if RC == 7
            % some additional combinations also apply
            validCombinations = [validCombinations;
                                614400      20; ...
                                307200      40; ...
                                153600      80];
        end
        
    elseif RC == 5 || RC == 8 || RC == 9
        %                     DataRate  FrameLength
        validCombinations = [   1800        20; ...
                                3600        20; ...
                                7200        20; ...
                                14400       20; ...
                                28800       20; ...
                                57600       20; ...
                                115200      20; ...
                                230400      20; ...
                                1800        40; ...
                                3600        40; ...
                                7200        40; ...
                                14400       40; ...
                                28800       40; ...
                                57600       40; ...
                                115200      40; ...
                                1800        80; ...
                                3600        80; ...
                                7200        80; ...
                                14400       80; ...
                                28800       80; ... 
                                57600       80  ]; 
        if RC == 8 || RC == 9
            % some additional combinations also apply
            validCombinations = [validCombinations;
                                460800      20; ...
                                230400      40; ...
                                115200      80];
        end
        
        if RC == 9
            % some additional combinations also apply
            validCombinations = [validCombinations;
                                1036800     20; ...
                                518400      40; ...
                                259200      80];
        end
    end
    
    waveformID = ['F-SCH-' num2str(dataRateSup) '-' num2str(frameLengthSup)];
    if ~any( ismember(validCombinations, [dataRateSup frameLengthSup], 'rows') )
        invalidIDerror(waveformID);
    end
end

function waveformStruct = createR_Traffic_Configuration(RC, dataRate, dataRateSup, frameLengthSup, numChips)
    
    % top-level waveform creation:    
    waveformStruct = createTopLevelWaveform(RC, numChips);    
    
    % add Forward Pilot Channel (F-PICH):
    fpich.Enable        = 'On';
    fpich.Power         = 0;
    waveformStruct.FPICH = fpich;
    
    % add Forward Fundamental Channel (F-FCH):
    ffch.Enable             = 'On';
    ffch.Power              = 0;
    ffch.RadioConfiguration = ['RC' num2str(RC)];
    ffch.DataRate           = dataRate;
    ffch.FrameLength        = 20;
    ffch.LongCodeMask       = 0;
    ffch.EnableCoding       = 'On';
    ffch.DataSource         = {'PN9', 1};
    ffch.WalshCode          = 1;
    ffch.EnableQOF          = 'Off';
    ffch.PowerControlEnable = 'Off';
    waveformStruct.FFCH = ffch;
    
    if RC == 1 || RC == 2
        
        % add Forward Supplemental Code Channel (F-SCCH):
        fscch.Enable        = 'On';
        fscch.Power         = 0;
        fscch.RadioConfiguration = ['RC' num2str(RC)];
        fscch.LongCodeMask  = 0;
        fscch.EnableCoding  = 'On';
        fscch.DataSource    = {'PN9', 1};
        fscch.WalshCode     = 2;
        waveformStruct.FSCCH = fscch;
        
    else % RC >= 3 && RC <= 9
        
        % add Forward Supplemental Channel (F-SCH):
        fsch.Enable             = 'On';
        fsch.Power              = 0;
        fsch.RadioConfiguration = ['RC' num2str(RC)];
        fsch.DataRate           = dataRateSup;
        fsch.FrameLength        = frameLengthSup;
        fsch.LongCodeMask       = 0;
        fsch.EnableCoding       = 'On';
        fsch.DataSource         = {'PN9', 1};
        fsch.WalshCode          = 2;
        fsch.EnableQOF          = 'Off';
        fsch.CodingType         = 'conv';
        waveformStruct.FSCH = fsch;
    end
end

function waveformStruct = createTXtestWaveform(RC, power, M ,numChips)

    % top-level waveform creation
    waveformStruct = createTopLevelWaveform(RC, numChips); % add common defaults
    
    % add Forward Pilot Channel (F-PICH):
    fpich.Enable         = 'On';
    fpich.Power          = power - 7;
    waveformStruct.FPICH = fpich;
    
    % add Forward Sync Channel (F-SYNC):
    fsync.Enable        = 'On';
    fsync.Power         = power - 13.3;
    fsync.EnableCoding  = 'On';
    fsync.DataSource    = {'PN9', 1};
    waveformStruct.FSYNC = fsync;
    
    if RC < 6 % RC 1-5
        
        % add Forward Paging Channel (F-PCH)
        fpch.Enable         = 'On';
        fpch.Power          = power - 7.3;
        fpch.LongCodeMask   = 0;
        fpch.DataRate       = 4800;
        fpch.EnableCoding   = 'On';
        fpch.DataSource     = {'PN9', 1};
        fpch.WalshCode      = 1;
        waveformStruct.FPCH = fpch;
        
    else % RC 6-9
        
        % add Forward Quick Paging Channel (F-QPCH)
        fqpch.Enable         = 'On';
        fqpch.Power          = power - 7.3;
        fqpch.LongCodeMask   = 0;
        fqpch.DataRate       = 2400;
        fqpch.EnableCoding   = 'On';
        fqpch.DataSource     = {'PN9', 1};
        fqpch.WalshCode      = 1;
        waveformStruct.FQPCH = fqpch;
    end
    
    % add M identical Forward Fundamental Channels (F-FCH):
    ffch.Enable             = 'On';
    ffch.Power              = power  - 2.48 - 10*log(M);
    ffch.RadioConfiguration = ['RC' num2str(RC)];
    if RC == 1 || RC == 3 || RC == 4 || RC == 6 || RC == 7
        ffch.DataRate       = 9600;
    else % if RC == 2 || RC == 5 || RC == 8 || RC == 9
        ffch.DataRate       = 14400;
    end
    ffch.FrameLength        = 20;
    ffch.LongCodeMask       = 0;
    ffch.EnableCoding       = 'On';
    ffch.DataSource         = {'PN9', 1};
    ffch.WalshCode          = 2;
    ffch.EnableQOF          = 'Off';
    ffch.PowerControlEnable = 'Off';
    waveformStruct.FFCH     = repmat(ffch, 1, M);
end

function waveformStruct = getAllChannels(RC, numChips)

    % top-level waveform creation
    waveformStruct = createTopLevelWaveform(RC, numChips);
    
    % channels for all RCs
    
    % Forward Pilot Channel (F-PICH):
    fpich.Enable         = 'On';
    fpich.Power          = 0;
    waveformStruct.FPICH = fpich;
    
    % Forward Auxiliary Pilot Channel (F-APICH):
    fapich.Enable         = 'On';
    fapich.Power          = 0;
    fapich.WalshCode      = 10;
    fapich.WalshLength    = 64;
    waveformStruct.FAPICH = fapich;
    
    % conditionally add some more pilot channels here, in this order
    if RC >= 1 && RC <= 5 
        
        % Forward Transmit Diversity Pilot Channel (F-TDPICH):
        ftdpich.Enable       = 'On';
        ftdpich.Power        = 0;
        waveformStruct.FTDPICH = ftdpich;
        
        % Forward Auxiliary Transmit Diversity Pilot Channel (F-ATDPICH):
        fatdpich.Enable         = 'On';
        fatdpich.Power          = 0;
        fatdpich.WalshCode      = 11;
        fatdpich.WalshLength    = 64;
        waveformStruct.FATDPICH   = fatdpich;
        
        % Forward Paging Channel (F-PCH)
        fpch.Enable         = 'On';
        fpch.Power          = 0;
        fpch.LongCodeMask   = 0;
        fpch.DataRate       = 4800;
        fpch.EnableCoding   = 'On';
        fpch.DataSource     = {'PN9', 1};
        fpch.WalshCode      = 1;
        waveformStruct.FPCH = fpch;
    end
    
    % again, channels for all RCs
    
    % Forward Sync Channel (F-SYNC)
    fsync.Enable            = 'On';
    fsync.Power             = 0;
    fsync.EnableCoding      = 'On';
    fsync.DataSource        = {'PN9', 1};
    waveformStruct.FSYNC    = fsync;
    
    % Forward Broadcase Control Channel (F-BCCH)
    fbcch.Enable            = 'On';
    fbcch.Power             = 0;
    fbcch.LongCodeMask      = 0;
    fbcch.DataRate          = 4800;
    fbcch.FrameLength       = 160;
    fbcch.EnableCoding      = 'On';
    fbcch.DataSource        = {'PN9', 1};
    fbcch.WalshCode         = 2;
    fbcch.CodingType        = 'conv';
    waveformStruct.FBCCH    = fbcch;
    
    % Forward Common Assignment Channel (F-CACH)
    fcach.Enable            = 'On';
    fcach.Power             = 0;
    fcach.LongCodeMask      = 0;
    fcach.EnableCoding      = 'On';
    fcach.DataSource        = {'PN9', 1};
    fcach.WalshCode         = 3;
    fcach.CodingType        = 'conv';
    waveformStruct.FCACH    = fcach;
    
    % Forward Common Control Channel (F-CCCH)
    fccch.Enable            = 'On';
    fccch.Power             = 0;
    fccch.LongCodeMask      = 0;
    fccch.DataRate          = 9600;
    fccch.FrameLength       = 20;
    fccch.EnableCoding      = 'On';
    fccch.DataSource        = {'PN9', 1};
    fccch.WalshCode         = 4;
    fccch.CodingType        = 'conv';
    waveformStruct.FCCCH    = fccch;
        
    % Forward Common Power Control Channel (F-CPCCH)
    fcpcch.Enable           = 'On';
    fcpcch.Power            = 0;
    fcpcch.LongCodeMask     = 0;
    fcpcch.EnableCoding     = 'On';
    fcpcch.DataSource       = {'PN9', 1};
    fcpcch.WalshCode        = 5;
    waveformStruct.FCPCCH   = fcpcch;
    
    % Forward Quick Paging Channel (F-QPCH)
    fqpch.Enable            = 'On';
    fqpch.Power             = 0;
    fqpch.LongCodeMask      = 0;
    fqpch.DataRate          = 2400;
    fqpch.EnableCoding      = 'On';
    fqpch.DataSource        = {'PN9',1};
    fqpch.WalshCode         = 6;
    waveformStruct.FQPCH    = fqpch;
    
    % Forward Fundamental Channel (F-FCH):
    ffch.Enable             = 'On';
    ffch.Power              = 0;
    ffch.RadioConfiguration = ['RC' num2str(RC)];
    if RC == 1 || RC == 3 || RC == 4 || RC == 6 || RC == 7
        ffch.DataRate       = 9600;
    else % if RC == 2 || RC == 5 || RC == 8 || RC == 9
        ffch.DataRate       = 14400;
    end
    ffch.FrameLength        = 20;
    ffch.LongCodeMask       = 0;
    ffch.EnableCoding       = 'On';
    ffch.DataSource         = {'PN9', 1};
    ffch.WalshCode          = 7;
    ffch.EnableQOF          = 'Off';
    ffch.PowerControlEnable = 'Off';
    waveformStruct.FFCH     = ffch;
    
    % Forward Orthogonal Channel Noise (F-OCNS)
    focns.Enable          = 'On';
    focns.Power           = -30.0;
    focns.WalshCode       = 12;
    focns.WalshLength     = 128;
    waveformStruct.FOCNS  = focns;
    
    % some RadioConfiguration-specific channels:
    
    if RC >= 3 && RC <= 5
        
        % Forward Dedicated Control Channel (F-DCCH)
        fdcch.Enable            = 'On';
        fdcch.Power             = 0;
        fdcch.RadioConfiguration = ['RC' num2str(RC)];
        fdcch.LongCodeMask      = 0;
        fdcch.DataRate          = 9600;
        fdcch.FrameLength       = 5;
        fdcch.EnableCoding      = 'On';
        fdcch.DataSource        = {'PN9',1};
        fdcch.WalshCode         = 8;
        fdcch.EnableQOF         = 'off';
        waveformStruct.FDCCH    = fdcch;
    end
    
    if RC == 1 || RC == 2
        
        % Forward Supplemental Code Channel (F-SCCH):
        fscch.Enable        = 'On';
        fscch.Power         = 0;
        fscch.RadioConfiguration = ['RC' num2str(RC)];
        fscch.LongCodeMask  = 0;
        fscch.EnableCoding  = 'On';
        fscch.DataSource    = {'PN9', 1};
        fscch.WalshCode     = 9;
        waveformStruct.FSCCH = fscch;
    end
    
    if RC >= 3 && RC <= 9
        
        % add Forward Supplemental Channel (F-SCH):
        fsch.Enable             = 'On';
        fsch.Power              = 0;
        fsch.RadioConfiguration = ['RC' num2str(RC)];
        if RC == 3 || RC == 4 || RC == 6 || RC == 7
            fsch.DataRate           = 9600;
        else % RC == 5 || RC == 8 || RC == 9
            fsch.DataRate           = 14400;
        end
        fsch.FrameLength        = 20;
        fsch.LongCodeMask       = 0;
        fsch.EnableCoding       = 'On';
        fsch.DataSource         = {'PN9', 1};
        fsch.WalshCode          = 9;
        fsch.EnableQOF          = 'Off';
        fsch.CodingType         = 'conv';
        waveformStruct.FSCH = fsch;
    end
    
end

function invalidIDerror(waveformID)
    invalidID       = 'comm:cdma2000evdoParameterGeneration:InvalidID';
    thisFunction    = 'cdma2000ForwardReferenceChannels';
    error(invalidID, getString( message(invalidID, waveformID, thisFunction, thisFunction)));
end
