function [s, codeword] = CmlEncode( data, sim_param, code_param )
% CmlEncode encodes and modulates a single codeword
%
% The calling syntax is:
%     [s, codeword] = CmlEncode( data, sim_param, code_param )
%
%     Outputs:
%     s = a row vector containing encoded and modulated symbols
%     codeword = the codeword generated by the encoder
%
%     Required inputs:
%     data = the row vector of data bits
%     sim_param = A structure containing simulation parameters.
%     code_param = A structure containing the code paramaters.
%
%     Copyright (C) 2005-2008, Matthew C. Valenti
%
%     Last updated on May 22, 2008
%
%     Function CmlEncode is part of the Iterative Solutions Coded Modulation
%     Library (ISCML).  
%
%     The Iterative Solutions Coded Modulation Library is free software;
%     you can redistribute it and/or modify it under the terms of 
%     the GNU Lesser General Public License as published by the 
%     Free Software Foundation; either version 2.1 of the License, 
%     or (at your option) any later version.
%
%     This library is distributed in the hope that it will be useful,
%     but WITHOUT ANY WARRANTY; without even the implied warranty of
%     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
%     Lesser General Public License for more details.
%
%     You should have received a copy of the GNU Lesser General Public
%     License along with this library; if not, write to the Free Software
%     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

if (code_param.coded)
    switch sim_param.code_configuration
        case {0} % convolutional code
            codeword = ConvEncode( data, sim_param.g1, sim_param.nsc_flag1 );
        
            % puncture [DOES NOT CURRENTLY WORK FOR TAIL-BITING CODES]
            if ( length (sim_param.pun_pattern1 ) )
                [N,K] = size( sim_param.g1 );
                codeword = reshape( codeword, N, length(codeword)/N );
                codeword = Puncture( codeword, sim_param.pun_pattern1, sim_param.tail_pattern1 );
            end
        case {1,4} % PCCC 
            codeword = TurboEncode( data, code_param.code_interleaver, code_param.pun_pattern, code_param.tail_pattern, sim_param.g1, sim_param.nsc_flag1, sim_param.g2, sim_param.nsc_flag2 );
        case {2} % LDPC
            codeword = LdpcEncode( data, code_param.H_rows, code_param.P_matrix );
        case {3} % HSDPA
            % generate a turbo codeword
            turbo_codeword = TurboEncode( data, code_param.code_interleaver, code_param.pun_pattern, code_param.tail_pattern, sim_param.g1, sim_param.nsc_flag1, sim_param.g2, sim_param.nsc_flag2 );

            % Rate Match according to the redundancy version
            M_arq = length(sim_param.X_set);
            for harq_transmission=1:M_arq
                [channel_streams] = HarqMatch( turbo_codeword, sim_param.X_set(harq_transmission), sim_param.N_IR, code_param.modulation, sim_param.P );
                harq_codeword(harq_transmission,:) = reshape( channel_streams', 1, code_param.number_codewords*code_param.N_data);
            end

            codeword = reshape( harq_codeword', 1, M_arq*code_param.N_data*code_param.number_codewords );
        case {5,6} % CTC code from WiMAX (5) or DVB-RCS (6)
            codeword = TurboDuobinaryCRSCEncode( data, code_param.code_interleaver, code_param.pun_pattern );
        case {7} % BTC code
            codeword = BtcEncode( data, sim_param.g1, sim_param.g2, sim_param.k_per_row, sim_param.k_per_column, sim_param.B, sim_param.Q );
    end
    
    % BICM interleave
    if ( length(code_param.bicm_interleaver) >= 1 )
        codeword = Interleave( codeword, code_param.bicm_interleaver );
    end
else
    codeword = data;
end

% modulate
s = Modulate( codeword, code_param.S_matrix );

