function param = tchFrameParam()
% param = tchFrameParam()
%   Returns parameters required for encoding and decoding augmented 3GPP 26.101
%   IF1 frames. See the command-line help for any of the codec executables for
%   more details.
%
% See also TCHWRITEFRAME, TCHREADFRAME.
%
% Copyright 2008, Research In Motion Limited.

    tchTypes = {'afs', 'fs', 'hs'};
    frameTypes = { ...
        [0:8 15], ...
        [18 19 15], ...
        [16 17 15], ...
    };
    stiBits = { ...
        {[], [], [], [], [], [], [], [], 8*7 + 4, []}, ...
        {[], [], []}, ...
        {[], [], []}, ...
    };
    nBytes = { ...
       {13, 14, 16, 18, 20, 21, 27, 32, 6, 0}, ...
       {34, 34, 0}, ...
       {15, 15, 0}, ...
    };

    % The frame bits are indexed as follows:
    %   index   1 ........... 8   9 .......... 16   ...
    %   octet |        1        |        2        | ...
    %   bit   | 7 6 5 4 3 2 1 0 | 7 6 5 4 3 2 1 0 | ...

    fqiBits = 5;
    b = [6:8];
    modeIndBits = { ...
        {b, b, b, b, b, b, b, b, 7*8 + [7 6 5], b, b}, ...
        {b, b, b}, ...
        {b, b, b}, ...
    };
    modeReqBits = 8 + [1:3];
    b = 2*8 + [1:8];
    crcBits = { ...
        {b, b, b, b, b, b, b, b, b, []}, ...
        {b, b, []}, ...
        {b, b, []}, ...
    };

    param = struct();
    % These are shared by all frame types
    param.frameTypeBits = [1:4];
    param.spareBits = 8 + [4:8];

    param.tchTypes = struct();
    param.tchModes = struct();
    param.frameTypes = struct();
    param.frameModes = struct();

    for iType = 1:length(tchTypes)
        info = tchParam(tchTypes{iType});
        tchModes = struct();
        typeMap = cell(1, 48);
        modeMap = cell(1, length(info.tchModes) - 2);
        for iMode = 1:length(frameTypes{iType})
            mode = info.tchModes{iMode};
            name = [info.tchType mode];

            % Place classBits at correct offset in frame
            cb = info.classBits(iMode, :);
            for i = 1:length(cb)
                cb{i} = cb{i} + 3*8;
            end

            t = struct( ...
                'tchType', info.tchType, ...
                'tchMode', info.tchModes{iMode}, ...
                'frameType', frameTypes{iType}(iMode), ...
                'fqiBits', fqiBits, ...
                'stiBits', stiBits{iType}(iMode), ...
                'modeIndBits', modeIndBits{iType}(iMode), ...
                'modeReqBits', modeReqBits, ...
                'classBits', {cb}, ...
                'crcBits', crcBits{iType}{iMode}, ...
                'nBytes', nBytes{iType}{iMode} ...
            );
            param.tchTypes = setfield(param.tchTypes, name, t);
            typeMap{frameTypes{iType}(iMode)+1} = name;
            if ~isequal(mode, 'SID') && ~isequal(mode, 'NODATA')
                param.tchModes = setfield(param.tchModes, name, iMode - 1);
                modeMap{iMode} = mode;
            end
        end
        param.frameTypes.(tchTypes{iType}) = typeMap;
        param.frameModes.(tchTypes{iType}) = modeMap;
    end
end
