/*******************************************************************************
    OpenAirInterface
    Copyright(c) 1999 - 2014 Eurecom

    OpenAirInterface is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.


    OpenAirInterface 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 General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with OpenAirInterface.The full GNU General Public License is
   included in this distribution in the file called "COPYING". If not,
   see <http://www.gnu.org/licenses/>.

  Contact Information
  OpenAirInterface Admin: openair_admin@eurecom.fr
  OpenAirInterface Tech : openair_tech@eurecom.fr
  OpenAirInterface Dev  : openair4g-devel@lists.eurecom.fr

  Address      : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE

 *******************************************************************************/
/* file: PHY/CODING/defs.h
   purpose: Top-level definitions, data types and function prototypes for openairinterface coding blocks
   author: raymond.knopp@eurecom.fr
   date: 21.10.2009
*/
#ifndef __CODING_DEFS__H__
#define __CODING_DEFS__H__

#include <stdint.h>

#ifndef NO_OPENAIR1
#include "PHY/defs.h"
#else
#include "PHY/TOOLS/time_meas.h"
#endif

#define CRC24_A 0
#define CRC24_B 1
#define CRC16 2
#define CRC8 3

#define MAX_TURBO_ITERATIONS_MBSFN 8
#define MAX_TURBO_ITERATIONS 4

#define LTE_NULL 2

/** @addtogroup _PHY_CODING_BLOCKS_
 * @{
*/

/** \fn lte_segmentation(uint8_t *input_buffer,
              uint8_t **output_buffers,
            uint32_t B,
            uint32_t *C,
            uint32_t *Cplus,
            uint32_t *Cminus,
            uint32_t *Kplus,
            uint32_t *Kminus,
            uint32_t *F)
\brief This function implements the LTE transport block segmentation algorithm from 36-212, V8.6 2009-03.
@param input_buffer
@param output_buffers
@param B
@param C
@param Cplus
@param Cminus
@param Kplus
@param Kminus
@param F
*/
int32_t lte_segmentation(uint8_t *input_buffer,
                         uint8_t **output_buffers,
                         uint32_t B,
                         uint32_t *C,
                         uint32_t *Cplus,
                         uint32_t *Cminus,
                         uint32_t *Kplus,
                         uint32_t *Kminus,
                         uint32_t *F);

/** \fn int16_t estimate_ue_tx_power(uint32_t tbs, uint32_t nb_rb, uint8_t control_only, lte_prefix_type_t ncp, uint8_t use_srs)
    \brief this functions calculates the delta MCS in dB based on the lte_segmentation function
\param tbs transport block size
\param nb_rb number of required rb
\param control_only a flag for the type of data
\param ncp cyclic prefix
\param use_srs a flag indicating the use of srs in the current SF
\returns ue_tx_power estimated ue tx power = delat_ mcs + bw_factor
*/
int16_t estimate_ue_tx_power(uint32_t tbs,
                             uint32_t nb_rb,
                             uint8_t control_only,
                             lte_prefix_type_t ncp,
                             uint8_t use_srs);

/** \fn uint32_t sub_block_interleaving_turbo(uint32_t D, uint8_t *d,uint8_t *w)
\brief This is the subblock interleaving algorithm from 36-212 (Release 8, 8.6 2009-03), pages 15-16.
This function takes the d-sequence and generates the w-sequence.  The nu-sequence from 36-212 is implicit.
\param D Number of systematic bits plus 4 (plus 4 for termination)
\param d Pointer to input (d-sequence, turbo code output)
\param w Pointer to output (w-sequence, interleaver output)
\returns Interleaving matrix cardinality (\f$K_{\pi}\f$  from 36-212)
*/
uint32_t sub_block_interleaving_turbo(uint32_t D, uint8_t *d,uint8_t *w);

/** \fn uint32_t sub_block_interleaving_cc(uint32_t D, uint8_t *d,uint8_t *w)
\brief This is the subblock interleaving algorithm for convolutionally coded blocks from 36-212 (Release 8, 8.6 2009-03), pages 15-16.
This function takes the d-sequence and generates the w-sequence.  The nu-sequence from 36-212 is implicit.
\param D Number of input bits
\param d Pointer to input (d-sequence, convolutional code output)
\param w Pointer to output (w-sequence, interleaver output)
\returns Interleaving matrix cardinality (\f$K_{\pi}\f$  from 36-212)
*/
uint32_t sub_block_interleaving_cc(uint32_t D, uint8_t *d,uint8_t *w);


/** \fn void sub_block_deinterleaving_turbo(uint32_t D, int16_t *d,int16_t *w)
\brief This is the subblock deinterleaving algorithm from 36-212 (Release 8, 8.6 2009-03), pages 15-16.
This function takes the w-sequence and generates the d-sequence.  The nu-sequence from 36-212 is implicit.
\param D Number of systematic bits plus 4 (plus 4 for termination)
\param d Pointer to output (d-sequence, turbo code output)
\param w Pointer to input (w-sequence, interleaver output)
*/
void sub_block_deinterleaving_turbo(uint32_t D, int16_t *d,int16_t *w);

/** \fn void sub_block_deinterleaving_cc(uint32_t D, int8_t *d,int8_t *w)
\brief This is the subblock deinterleaving algorithm for convolutionally-coded data from 36-212 (Release 8, 8.6 2009-03), pages 15-16.
This function takes the w-sequence and generates the d-sequence.  The nu-sequence from 36-212 is implicit.
\param D Number of input bits
\param d Pointer to output (d-sequence, turbo code output)
\param w Pointer to input (w-sequence, interleaver output)
*/
void sub_block_deinterleaving_cc(uint32_t D,int8_t *d,int8_t *w);

/** \fn generate_dummy_w(uint32_t D, uint8_t *w,uint8_t F)
\brief This function generates a dummy interleaved sequence (first row) for receiver, in order to identify
the NULL positions used to make the matrix complete.
\param D Number of systematic bits plus 4 (plus 4 for termination)
\param w This is the dummy sequence (first row), it will contain zeros and at most 31 "LTE_NULL" values
\param F Number of filler bits due added during segmentation
\returns Interleaving matrix cardinality (\f$K_{\pi}\f$ from 36-212)
*/

uint32_t generate_dummy_w(uint32_t D, uint8_t *w, uint8_t F);

/** \fn generate_dummy_w_cc(uint32_t D, uint8_t *w)
\brief This function generates a dummy interleaved sequence (first row) for receiver (convolutionally-coded data), in order to identify the NULL positions used to make the matrix complete.
\param D Number of systematic bits plus 4 (plus 4 for termination)
\param w This is the dummy sequence (first row), it will contain zeros and at most 31 "LTE_NULL" values
\returns Interleaving matrix cardinality (\f$K_{\pi}\f$ from 36-212)
*/
uint32_t generate_dummy_w_cc(uint32_t D, uint8_t *w);

/** \fn uint32_t lte_rate_matching_turbo(uint32_t RTC,
           uint32_t G,
           uint8_t *w,
           uint8_t *e,
           uint8_t C,
           uint32_t Nsoft,
           uint8_t Mdlharq,
           uint8_t Kmimo,
           uint8_t rvidx,
           uint8_t Qm,
           uint8_t Nl,
           uint8_t r)

\brief This is the LTE rate matching algorithm for Turbo-coded channels (e.g. DLSCH,ULSCH).  It is taken directly from 36-212 (Rel 8 8.6, 2009-03), pages 16-18 )
\param RTC R^TC_subblock from subblock interleaver (number of rows in interleaving matrix) for up to 8 segments
\param G This the number of coded transport bits allocated in sub-frame
\param w This is a pointer to the w-sequence (second interleaver output)
\param e This is a pointer to the e-sequence (rate matching output, channel input/output bits)
\param C Number of segments (codewords) in the sub-frame
\param Nsoft Total number of soft bits (from UE capabilities in 36-306)
\param Mdlharq Number of HARQ rounds
\param Kmimo MIMO capability for this DLSCH (0 = no MIMO)
\param rvidx round index (0-3)
\param Qm modulation order (2,4,6)
\param Nl number of layers (1,2)
\param r segment number
\returns \f$E\f$, the number of coded bits per segment */


uint32_t lte_rate_matching_turbo(uint32_t RTC,
                                 uint32_t G,
                                 uint8_t *w,
                                 uint8_t *e,
                                 uint8_t C,
                                 uint32_t Nsoft,
                                 uint8_t Mdlharq,
                                 uint8_t Kmimo,
                                 uint8_t rvidx,
                                 uint8_t Qm,
                                 uint8_t Nl,
                                 uint8_t r,
                                 uint8_t nb_rb,
                                 uint8_t m);

/**
\brief This is the LTE rate matching algorithm for Convolutionally-coded channels (e.g. BCH,DCI,UCI).  It is taken directly from 36-212 (Rel 8 8.6, 2009-03), pages 16-18 )
\param RCC R^CC_subblock from subblock interleaver (number of rows in interleaving matrix) for up to 8 segments
\param E Number of coded channel bits
\param w This is a pointer to the w-sequence (second interleaver output)
\param e This is a pointer to the e-sequence (rate matching output, channel input/output bits)
\returns \f$E\f$, the number of coded bits per segment */

uint32_t lte_rate_matching_cc(uint32_t RCC,
                              uint16_t E,
                              uint8_t *w,
                              uint8_t *e);

/**
\brief This is the LTE rate matching algorithm for Turbo-coded channels (e.g. DLSCH,ULSCH).  It is taken directly from 36-212 (Rel 8 8.6, 2009-03), pages 16-18 )
\param RTC R^TC_subblock from subblock interleaver (number of rows in interleaving matrix)
\param G This the number of coded transport bits allocated in sub-frame
\param w This is a pointer to the soft w-sequence (second interleaver output) with soft-combined outputs from successive HARQ rounds
\param dummy_w This is the first row of the interleaver matrix for identifying/discarding the "LTE-NULL" positions
\param soft_input This is a pointer to the soft channel output
\param C Number of segments (codewords) in the sub-frame
\param Nsoft Total number of soft bits (from UE capabilities in 36-306)
\param Mdlharq Number of HARQ rounds
\param Kmimo MIMO capability for this DLSCH (0 = no MIMO)
\param rvidx round index (0-3)
\param clear 1 means clear soft buffer (start of HARQ round)
\param Qm modulation order (2,4,6)
\param Nl number of layers (1,2)
\param r segment number
\param E_out the number of coded bits per segment
\returns 0 on success, -1 on failure
*/

int lte_rate_matching_turbo_rx(uint32_t RTC,
                               uint32_t G,
                               int16_t *w,
                               uint8_t *dummy_w,
                               int16_t *soft_input,
                               uint8_t C,
                               uint32_t Nsoft,
                               uint8_t Mdlharq,
                               uint8_t Kmimo,
                               uint8_t rvidx,
                               uint8_t clear,
                               uint8_t Qm,
                               uint8_t Nl,
                               uint8_t r,
                               uint32_t *E_out);

uint32_t lte_rate_matching_turbo_rx_abs(uint32_t RTC,
                                        uint32_t G,
                                        double *w,
                                        uint8_t *dummy_w,
                                        double *soft_input,
                                        uint8_t C,
                                        uint32_t Nsoft,
                                        uint8_t Mdlharq,
                                        uint8_t Kmimo,
                                        uint8_t rvidx,
                                        uint8_t clear,
                                        uint8_t Qm,
                                        uint8_t Nl,
                                        uint8_t r,
                                        uint32_t *E_out);
/**

\brief This is the LTE rate matching algorithm for Convolutionally-coded channels (e.g. BCH,DCI,UCI).  It is taken directly from 36-212 (Rel 8 8.6, 2009-03), pages 16-18 )
\param RCC R^CC_subblock from subblock interleaver (number of rows in interleaving matrix)
\param E This the number of coded bits allocated for channel
\param w This is a pointer to the soft w-sequence (second interleaver output) with soft-combined outputs from successive HARQ rounds
\param dummy_w This is the first row of the interleaver matrix for identifying/discarding the "LTE-NULL" positions
\param soft_input This is a pointer to the soft channel output
\returns \f$E\f$, the number of coded bits per segment
*/
void lte_rate_matching_cc_rx(uint32_t RCC,
                             uint16_t E,
                             int8_t *w,
                             uint8_t *dummy_w,
                             int8_t *soft_input);

/** \fn void ccodedot11_encode(uint32_t numbytes,uint8_t *inPtr,uint8_t *outPtr,uint8_t puncturing)
\brief This function implements a rate 1/2 constraint length 7 convolutional code.
@param numbytes Number of bytes to encode
@param inPtr Pointer to input buffer
@param outPtr Pointer to output buffer
@param puncturing Puncturing pattern (Not used at present, to be removed)
*/
void ccodedot11_encode (uint32_t numbytes,
                        uint8_t *inPtr,
                        uint8_t *outPtr,
                        uint8_t puncturing);

/*!\fn void ccodedot11_init(void)
\brief This function initializes the generator polynomials for an 802.11 convolutional code.*/
void ccodedot11_init(void);

/*!\fn void ccodedot11_init_inv(void)
\brief This function initializes the trellis structure for decoding an 802.11 convolutional code.*/
void ccodedot11_init_inv(void);

/*!\fn void teillis_table_init(void)
\brief This function initializes the trellis structure for 3GPP LTE Turbo code.*/
void treillis_table_init(void);

/*\fn void threegpplte_turbo_encoder(uint8_t *input,uint16_t input_length_bytes,uint8_t *output,uint8_t F,uint16_t interleaver_f1,uint16_t interleaver_f2)
\brief This function implements a rate 1/3 8-state parralel concatenated turbo code (3GPP-LTE).
@param input Pointer to input buffer
@param input_length_bytes Number of bytes to encode
@param output Pointer to output buffer
@param F Number of filler bits at input
@param interleaver_f1 F1 generator
@param interleaver_f2 F2 generator
*/
void threegpplte_turbo_encoder(uint8_t *input,
                               uint16_t input_length_bytes,
                               uint8_t *output,
                               uint8_t F,
                               uint16_t interleaver_f1,
                               uint16_t interleaver_f2);


/** \fn void ccodelte_encode(int32_t numbits,uint8_t add_crc, uint8_t *inPtr,uint8_t *outPtr,uint16_t rnti)
\brief This function implements the LTE convolutional code of rate 1/3
  with a constraint length of 7 bits. The inputs are bit packed in octets
(from MSB to LSB). Trellis tail-biting is included here.
@param numbits Number of bits to encode
@param add_crc crc to be appended (8 bits) if add_crc = 1
@param inPtr Pointer to input buffer
@param outPtr Pointer to output buffer
@param rnti RNTI for CRC scrambling
*/
void
ccodelte_encode (int32_t numbits,
                 uint8_t add_crc,
                 uint8_t *inPtr,
                 uint8_t *outPtr,
                 uint16_t rnti);

/*!\fn void ccodelte_init(void)
\brief This function initializes the generator polynomials for an LTE convolutional code.*/
void ccodelte_init(void);

/*!\fn void ccodelte_init_inv(void)
\brief This function initializes the trellis structure for decoding an LTE convolutional code.*/
void ccodelte_init_inv(void);

/*!\fn void ccodelte_init(void)
\brief This function initializes the generator polynomials for an DAB convolutional code (first 3 bits).*/
void ccodedab_init(void);

/*!\fn void ccodelte_init_inv(void)
\brief This function initializes the trellis structure for decoding an DAB convolutional code (first 3 bits).*/
void ccodedab_init_inv(void);



/*!\fn void crcTableInit(void)
\brief This function initializes the different crc tables.*/
void crcTableInit (void);

/*!\fn void init_td8(void)
\brief This function initializes the tables for 8-bit LLR Turbo decoder.*/
void init_td8 (void);


/*!\fn void init_td16(void)
\brief This function initializes the tables for 16-bit LLR Turbo decoder.*/
void init_td16 (void);

#ifdef __AVX2__
/*!\fn void init_td8(void)
\brief This function initializes the tables for 8-bit LLR Turbo decoder (AVX2).*/
void init_td8avx2 (void);


/*!\fn void init_td16(void)
\brief This function initializes the tables for 16-bit LLR Turbo decoder (AVX2).*/
void init_td16avx2 (void);
#endif

/*!\fn uint32_t crc24a(uint8_t *inPtr, int32_t bitlen)
\brief This computes a 24-bit crc ('a' variant for overall transport block)
based on 3GPP UMTS/LTE specifications.
@param inPtr Pointer to input byte stream
@param bitlen length of inputs in bits
*/
uint32_t crc24a (uint8_t *inPtr, int32_t bitlen);

/*!\fn uint32_t crc24b(uint8_t *inPtr, int32_t bitlen)
\brief This computes a 24-bit crc ('b' variant for transport-block segments)
based on 3GPP UMTS/LTE specifications.
@param inPtr Pointer to input byte stream
@param bitlen length of inputs in bits
*/
uint32_t crc24b (uint8_t *inPtr, int32_t bitlen);

/*!\fn uint32_t crc16(uint8_t *inPtr, int32_t bitlen)
\brief This computes a 16-bit crc based on 3GPP UMTS specifications.
@param inPtr Pointer to input byte stream
@param bitlen length of inputs in bits*/
uint32_t crc16 (uint8_t *inPtr, int32_t bitlen);

/*!\fn uint32_t crc12(uint8_t *inPtr, int32_t bitlen)
\brief This computes a 12-bit crc based on 3GPP UMTS specifications.
@param inPtr Pointer to input byte stream
@param bitlen length of inputs in bits*/
uint32_t crc12 (uint8_t *inPtr, int32_t bitlen);

/*!\fn uint32_t crc8(uint8_t *inPtr, int32_t bitlen)
\brief This computes a 8-bit crc based on 3GPP UMTS specifications.
@param inPtr Pointer to input byte stream
@param bitlen length of inputs in bits*/
uint32_t crc8  (uint8_t *inPtr, int32_t bitlen);

/*!\fn void phy_viterbi_dot11_sse2(int8_t *y, uint8_t *decoded_bytes, uint16_t n,int offset,int traceback)
\brief This routine performs a SIMD optmized Viterbi decoder for the 802.11 64-state convolutional code. It can be
run in segments with final trace back after last segment.
@param y Pointer to soft input (coded on 8-bits but should be limited to 4-bit precision to avoid overflow)
@param decoded_bytes Pointer to decoded output
@param n Length of input/trellis depth in bits for this run
@param offset offset in receive buffer for segment on which to operate
@param traceback flag to indicate that traceback should be performed*/
void phy_viterbi_dot11_sse2(int8_t *y,uint8_t *decoded_bytes,uint16_t n);

/*!\fn void phy_viterbi_lte_sse2(int8_t *y, uint8_t *decoded_bytes, uint16_t n)
\brief This routine performs a SIMD optmized Viterbi decoder for the LTE 64-state tail-biting convolutional code.
@param y Pointer to soft input (coded on 8-bits but should be limited to 4-bit precision to avoid overflow)
@param decoded_bytes Pointer to decoded output
@param n Length of input/trellis depth in bits*/
//void phy_viterbi_lte_sse2(int8_t *y,uint8_t *decoded_bytes,uint16_t n);
void phy_viterbi_lte_sse2(int8_t *y,uint8_t *decoded_bytes,uint16_t n);

/*!\fn void phy_generate_viterbi_tables(void)
\brief This routine initializes metric tables for the optimized Viterbi decoder.
*/
void phy_generate_viterbi_tables( void );

/*!\fn void phy_generate_viterbi_tables_lte(void)
\brief This routine initializes metric tables for the optimized LTE Viterbi decoder.
*/
void phy_generate_viterbi_tables_lte( void );


/*!\fn int32_t rate_matching(uint32_t N_coded,
             uint32_t N_input,
             uint8_t *inPtr,
             uint8_t N_bps,
             uint32_t off)
\brief This routine performs random puncturing of a coded sequence.
@param N_coded Number of coding bits to be output
@param N_input Number of input bits
@param *inPtr Pointer to coded input
@param N_bps Number of modulation bits per symbol (1,2,4)
@param off Offset for seed

*/
int32_t rate_matching(uint32_t N_coded,
                      uint32_t N_input,
                      uint8_t *inPtr,
                      uint8_t N_bps,
                      uint32_t off);

int32_t rate_matching_lte(uint32_t N_coded,
                          uint32_t N_input,
                          uint8_t *inPtr,
                          uint32_t off);


/*!
\brief This routine performs max-logmap detection for the 3GPP turbo code (with termination).  It is optimized for SIMD processing and 16-bit
LLR arithmetic, and requires SSE2,SSSE3 and SSE4.1 (gcc >=4.3 and appropriate CPU)
@param y LLR input (16-bit precision)
@param decoded_bytes Pointer to decoded output
@param n number of coded bits (including tail bits)
@param max_iterations The maximum number of iterations to perform
@param interleaver_f1 F1 generator
@param interleaver_f2 F2 generator
@param crc_type Length of 3GPPLTE crc (CRC24a,CRC24b,CRC16,CRC8)
@param F Number of filler bits at start of packet
@returns number of iterations used (this is 1+max if incorrect crc or if crc_len=0)
*/
uint8_t phy_threegpplte_turbo_decoder16(int16_t *y,
                                        uint8_t *decoded_bytes,
                                        uint16_t n,
                                        uint16_t interleaver_f1,
                                        uint16_t interleaver_f2,
                                        uint8_t max_iterations,
                                        uint8_t crc_type,
                                        uint8_t F,
                                        time_stats_t *init_stats,
                                        time_stats_t *alpha_stats,
                                        time_stats_t *beta_stats,
                                        time_stats_t *gamma_stats,
                                        time_stats_t *ext_stats,
                                        time_stats_t *intl1_stats,
                                        time_stats_t *intl2_stats);

uint8_t phy_threegpplte_turbo_decoder16avx2(int16_t *y,
					    int16_t *y2,
					    uint8_t *decoded_bytes,
					    uint8_t *decoded_bytes2,
					    uint16_t n,
					    uint16_t interleaver_f1,
					    uint16_t interleaver_f2,
					    uint8_t max_iterations,
					    uint8_t crc_type,
					    uint8_t F,
					    time_stats_t *init_stats,
					    time_stats_t *alpha_stats,
					    time_stats_t *beta_stats,
					    time_stats_t *gamma_stats,
					    time_stats_t *ext_stats,
					    time_stats_t *intl1_stats,
					    time_stats_t *intl2_stats);

/*!
\brief This routine performs max-logmap detection for the 3GPP turbo code (with termination).  It is optimized for SIMD processing and 8-bit
LLR arithmetic, and requires SSE2,SSSE3 and SSE4.1 (gcc >=4.3 and appropriate CPU)
@param y LLR input (16-bit precision)
@param decoded_bytes Pointer to decoded output
@param n number of coded bits (including tail bits)
@param max_iterations The maximum number of iterations to perform
@param interleaver_f1 F1 generator
@param interleaver_f2 F2 generator
@param crc_type Length of 3GPPLTE crc (CRC24a,CRC24b,CRC16,CRC8)
@param F Number of filler bits at start of packet
@returns number of iterations used (this is 1+max if incorrect crc or if crc_len=0)
*/
uint8_t phy_threegpplte_turbo_decoder8(int16_t *y,
                                       uint8_t *decoded_bytes,
                                       uint16_t n,
                                       uint16_t interleaver_f1,
                                       uint16_t interleaver_f2,
                                       uint8_t max_iterations,
                                       uint8_t crc_type,
                                       uint8_t F,
                                       time_stats_t *init_stats,
                                       time_stats_t *alpha_stats,
                                       time_stats_t *beta_stats,
                                       time_stats_t *gamma_stats,
                                       time_stats_t *ext_stats,
                                       time_stats_t *intl1_stats,
                                       time_stats_t *intl2_stats);

uint8_t phy_threegpplte_turbo_decoder_scalar(int16_t *y,
    uint8_t *decoded_bytes,
    uint16_t n,
    uint16_t interleaver_f1,
    uint16_t interleaver_f2,
    uint8_t max_iterations,
    uint8_t crc_type,
    uint8_t F,
    uint8_t inst);



/** @} */

uint32_t crcbit (uint8_t * ,
                 int32_t,
                 uint32_t);

int16_t reverseBits(int32_t ,int32_t);
void phy_viterbi_dot11(int8_t *,uint8_t *,uint16_t);

#endif
