mirror of https://github.com/pvnis/srsRAN_4G.git
commit
d7d0f3ee94
@ -0,0 +1,73 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* \section COPYRIGHT
|
||||||
|
*
|
||||||
|
* Copyright 2013-2014 The libLTE Developers. See the
|
||||||
|
* COPYRIGHT file at the top-level directory of this distribution.
|
||||||
|
*
|
||||||
|
* \section LICENSE
|
||||||
|
*
|
||||||
|
* This file is part of the libLTE library.
|
||||||
|
*
|
||||||
|
* libLTE 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 3 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* libLTE 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.
|
||||||
|
*
|
||||||
|
* A copy of the GNU Lesser General Public License can be found in
|
||||||
|
* the LICENSE file in the top-level directory of this distribution
|
||||||
|
* and at http://www.gnu.org/licenses/.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef RM_TURBO_
|
||||||
|
#define RM_TURBO_
|
||||||
|
|
||||||
|
#ifndef RX_NULL
|
||||||
|
#define RX_NULL 10000
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef TX_NULL
|
||||||
|
#define TX_NULL 80
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int buffer_len;
|
||||||
|
char *buffer;
|
||||||
|
int *d2_perm;
|
||||||
|
} rm_turbo_t;
|
||||||
|
|
||||||
|
int rm_turbo_init(rm_turbo_t *q, int max_codeblock_len);
|
||||||
|
void rm_turbo_free(rm_turbo_t *q);
|
||||||
|
int rm_turbo_tx(rm_turbo_t *q, char *input, int in_len, char *output, int out_len, int rv_idx);
|
||||||
|
int rm_turbo_rx(rm_turbo_t *q, float *input, int in_len, float *output, int out_len, int rv_idx);
|
||||||
|
|
||||||
|
|
||||||
|
/* High-level API */
|
||||||
|
typedef struct {
|
||||||
|
rm_turbo_t q;
|
||||||
|
struct rm_turbo_init {
|
||||||
|
int direction;
|
||||||
|
} init;
|
||||||
|
void *input; // input type may be char or float depending on hard
|
||||||
|
int in_len;
|
||||||
|
struct rm_turbo_ctrl_in {
|
||||||
|
int E;
|
||||||
|
int S;
|
||||||
|
int rv_idx;
|
||||||
|
} ctrl_in;
|
||||||
|
void *output;
|
||||||
|
int out_len;
|
||||||
|
}rm_turbo_hl;
|
||||||
|
|
||||||
|
int rm_turbo_initialize(rm_turbo_hl* h);
|
||||||
|
int rm_turbo_work(rm_turbo_hl* hl);
|
||||||
|
int rm_turbo_stop(rm_turbo_hl* hl);
|
||||||
|
|
||||||
|
#endif
|
@ -0,0 +1,41 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* \section COPYRIGHT
|
||||||
|
*
|
||||||
|
* Copyright 2013-2014 The libLTE Developers. See the
|
||||||
|
* COPYRIGHT file at the top-level directory of this distribution.
|
||||||
|
*
|
||||||
|
* \section LICENSE
|
||||||
|
*
|
||||||
|
* This file is part of the libLTE library.
|
||||||
|
*
|
||||||
|
* libLTE 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 3 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* libLTE 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.
|
||||||
|
*
|
||||||
|
* A copy of the GNU Lesser General Public License can be found in
|
||||||
|
* the LICENSE file in the top-level directory of this distribution
|
||||||
|
* and at http://www.gnu.org/licenses/.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _PERMUTE_H
|
||||||
|
#define _PERMUTE_H
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int *forward;
|
||||||
|
int *reverse;
|
||||||
|
}tc_interl_t;
|
||||||
|
|
||||||
|
int tc_interl_LTE_init(tc_interl_t *h, int long_cb);
|
||||||
|
int tc_interl_UMTS_init(tc_interl_t *h, int long_cb);
|
||||||
|
|
||||||
|
void tc_interl_free(tc_interl_t *h);
|
||||||
|
|
||||||
|
#endif
|
@ -0,0 +1,45 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* \section COPYRIGHT
|
||||||
|
*
|
||||||
|
* Copyright 2013-2014 The libLTE Developers. See the
|
||||||
|
* COPYRIGHT file at the top-level directory of this distribution.
|
||||||
|
*
|
||||||
|
* \section LICENSE
|
||||||
|
*
|
||||||
|
* This file is part of the libLTE library.
|
||||||
|
*
|
||||||
|
* libLTE 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 3 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* libLTE 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.
|
||||||
|
*
|
||||||
|
* A copy of the GNU Lesser General Public License can be found in
|
||||||
|
* the LICENSE file in the top-level directory of this distribution
|
||||||
|
* and at http://www.gnu.org/licenses/.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#define NUMREGS 3
|
||||||
|
|
||||||
|
#define RATE 3
|
||||||
|
#define TOTALTAIL 12
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int long_cb;
|
||||||
|
tc_interl_t interl;
|
||||||
|
|
||||||
|
}tcod_t;
|
||||||
|
|
||||||
|
int tcod_init(tcod_t *h, int long_cb);
|
||||||
|
void tcod_free(tcod_t *h);
|
||||||
|
void tcod_encode(tcod_t *h, char *input, char *output);
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,44 @@
|
|||||||
|
#define RATE 3
|
||||||
|
#define TOTALTAIL 12
|
||||||
|
|
||||||
|
#define LOG18 -2.07944
|
||||||
|
|
||||||
|
#define NUMSTATES 8
|
||||||
|
#define NINPUTS 2
|
||||||
|
#define TAIL 3
|
||||||
|
#define TOTALTAIL 12
|
||||||
|
|
||||||
|
#define INF 9e4
|
||||||
|
#define ZERO 9e-4
|
||||||
|
|
||||||
|
#define MAX_LONG_CB 6114
|
||||||
|
#define MAX_LONG_CODED (RATE*MAX_LONG_CB+TOTALTAIL)
|
||||||
|
|
||||||
|
typedef float llr_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int long_cb;
|
||||||
|
llr_t *beta;
|
||||||
|
}map_gen_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int long_cb;
|
||||||
|
|
||||||
|
map_gen_t dec;
|
||||||
|
|
||||||
|
llr_t *llr1;
|
||||||
|
llr_t *llr2;
|
||||||
|
llr_t *w;
|
||||||
|
llr_t *syst;
|
||||||
|
llr_t *parity;
|
||||||
|
|
||||||
|
tc_interl_t interleaver;
|
||||||
|
}tdec_t;
|
||||||
|
|
||||||
|
int tdec_init(tdec_t *h, int long_cb);
|
||||||
|
void tdec_free(tdec_t *h);
|
||||||
|
|
||||||
|
void tdec_reset(tdec_t *h);
|
||||||
|
void tdec_iteration(tdec_t *h, llr_t *input);
|
||||||
|
void tdec_decision(tdec_t *h, char *output);
|
||||||
|
void tdec_run_all(tdec_t *h, llr_t *input, char *output, int nof_iterations);
|
@ -0,0 +1,156 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* \section COPYRIGHT
|
||||||
|
*
|
||||||
|
* Copyright 2013-2014 The libLTE Developers. See the
|
||||||
|
* COPYRIGHT file at the top-level directory of this distribution.
|
||||||
|
*
|
||||||
|
* \section LICENSE
|
||||||
|
*
|
||||||
|
* This file is part of the libLTE library.
|
||||||
|
*
|
||||||
|
* libLTE 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 3 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* libLTE 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.
|
||||||
|
*
|
||||||
|
* A copy of the GNU Lesser General Public License can be found in
|
||||||
|
* the LICENSE file in the top-level directory of this distribution
|
||||||
|
* and at http://www.gnu.org/licenses/.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef RB_ALLOC_H_
|
||||||
|
#define RB_ALLOC_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
/** Structures and utility functions for DL/UL resource
|
||||||
|
* allocation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
MOD_NULL = 0, BPSK = 1, QPSK = 2, QAM16 = 4, QAM64 = 16
|
||||||
|
} ra_mod_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ra_mod_t mod; // By default, mod = MOD_NULL and the mcs_idx value is taken by the packing functions
|
||||||
|
// otherwise mod + tbs values are used to generate the mcs_idx automatically.
|
||||||
|
uint8_t tbs_idx;
|
||||||
|
uint8_t mcs_idx;
|
||||||
|
int tbs; // If tbs<=0, the tbs_idx value is taken by the packing functions to generate the DCI
|
||||||
|
// message. Otherwise the tbs_idx corresponding to the lower nearest TBS is taken.
|
||||||
|
}ra_mcs_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
alloc_type0 = 0, alloc_type1 = 1, alloc_type2 = 2
|
||||||
|
}ra_type_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t rbg_bitmask;
|
||||||
|
}ra_type0_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t vrb_bitmask;
|
||||||
|
uint8_t rbg_subset;
|
||||||
|
bool shift;
|
||||||
|
}ra_type1_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t riv; // if L_crb==0, DCI message packer will take this value directly
|
||||||
|
uint16_t L_crb;
|
||||||
|
uint16_t RB_start;
|
||||||
|
enum {nprb1a_2 = 0, nprb1a_3 = 1} n_prb1a;
|
||||||
|
enum {t2_ng1 = 0, t2_ng2 = 1} n_gap;
|
||||||
|
enum {t2_loc = 0, t2_dist = 1} mode;
|
||||||
|
}ra_type2_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned short rnti;
|
||||||
|
ra_type_t alloc_type;
|
||||||
|
union {
|
||||||
|
ra_type0_t type0_alloc;
|
||||||
|
ra_type1_t type1_alloc;
|
||||||
|
ra_type2_t type2_alloc;
|
||||||
|
};
|
||||||
|
ra_mcs_t mcs;
|
||||||
|
uint8_t harq_process;
|
||||||
|
uint8_t rv_idx;
|
||||||
|
bool ndi;
|
||||||
|
} ra_pdsch_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
/* 36.213 Table 8.4-2: hop_half is 0 for < 10 Mhz and 10 for > 10 Mh.
|
||||||
|
* hop_quart is 00 for > 10 Mhz and hop_quart_neg is 01 for > 10 Mhz.
|
||||||
|
*/
|
||||||
|
enum {
|
||||||
|
hop_disabled = -1,
|
||||||
|
hop_quart = 0,
|
||||||
|
hop_quart_neg = 1,
|
||||||
|
hop_half = 2,
|
||||||
|
hop_type_2 = 3
|
||||||
|
} freq_hop_fl;
|
||||||
|
|
||||||
|
ra_type2_t type2_alloc;
|
||||||
|
ra_mcs_t mcs;
|
||||||
|
uint8_t rv_idx; // If set to non-zero, a retransmission is requested with the same modulation
|
||||||
|
// than before (Format0 message, see also 8.6.1 in 36.2313).
|
||||||
|
bool ndi;
|
||||||
|
bool cqi_request;
|
||||||
|
|
||||||
|
} ra_pusch_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t prb_idx[110];
|
||||||
|
int nof_prb;
|
||||||
|
}ra_prb_slot_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ra_prb_slot_t slot1;
|
||||||
|
ra_prb_slot_t slot2;
|
||||||
|
bool is_dist;
|
||||||
|
}ra_prb_t;
|
||||||
|
|
||||||
|
|
||||||
|
void ra_prb_fprint(FILE *f, ra_prb_slot_t *prb);
|
||||||
|
int ra_prb_get_dl(ra_prb_t *prb, ra_pdsch_t *ra, int nof_prb);
|
||||||
|
int ra_prb_get_ul(ra_prb_slot_t *prb, ra_pusch_t *ra, int nof_prb);
|
||||||
|
int ra_nprb_dl(ra_pdsch_t *ra, int nof_prb);
|
||||||
|
int ra_nprb_ul(ra_pusch_t *ra, int nof_prb);
|
||||||
|
|
||||||
|
uint8_t ra_mcs_to_table_idx(ra_mcs_t *mcs);
|
||||||
|
int ra_mcs_from_idx_dl(uint8_t idx, ra_mcs_t *mcs);
|
||||||
|
int ra_mcs_from_idx_ul(uint8_t idx, ra_mcs_t *mcs);
|
||||||
|
int ra_tbs_from_idx_format1c(uint8_t tbs_idx);
|
||||||
|
int ra_tbs_to_table_idx_format1c(int tbs);
|
||||||
|
int ra_tbs_from_idx(uint8_t tbs_idx, int n_prb);
|
||||||
|
int ra_tbs_to_table_idx(int tbs, int n_prb);
|
||||||
|
|
||||||
|
uint8_t ra_mcs_to_table_idx(ra_mcs_t *mcs);
|
||||||
|
int ra_mcs_from_idx_dl(uint8_t idx, ra_mcs_t *mcs);
|
||||||
|
int ra_mcs_from_idx_ul(uint8_t idx, ra_mcs_t *mcs);
|
||||||
|
|
||||||
|
char *ra_mod_string(ra_mod_t mod);
|
||||||
|
|
||||||
|
int ra_type0_P(int nof_prb);
|
||||||
|
|
||||||
|
uint32_t ra_type2_to_riv(uint16_t L_crb, uint16_t RB_start, int nof_prb);
|
||||||
|
void ra_type2_from_riv(uint32_t riv, uint16_t *L_crb, uint16_t *RB_start, int nof_prb, int nof_vrb);
|
||||||
|
int ra_type2_n_vrb_dl(int nof_prb, bool ngap_is_1);
|
||||||
|
int ra_type2_n_rb_step(int nof_prb);
|
||||||
|
int ra_type2_ngap(int nof_prb, bool ngap_is_1);
|
||||||
|
int ra_type1_N_rb(int nof_prb);
|
||||||
|
|
||||||
|
void ra_pdsch_set_mcs_index(ra_pdsch_t *ra, uint8_t mcs_idx);
|
||||||
|
void ra_pdsch_set_mcs(ra_pdsch_t *ra, ra_mod_t mod, uint8_t tbs_idx);
|
||||||
|
void ra_pdsch_fprint(FILE *f, ra_pdsch_t *ra, int nof_prb);
|
||||||
|
void ra_pusch_fprint(FILE *f, ra_pusch_t *ra, int nof_prb);
|
||||||
|
|
||||||
|
#endif /* RB_ALLOC_H_ */
|
@ -0,0 +1,262 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* \section COPYRIGHT
|
||||||
|
*
|
||||||
|
* Copyright 2013-2014 The libLTE Developers. See the
|
||||||
|
* COPYRIGHT file at the top-level directory of this distribution.
|
||||||
|
*
|
||||||
|
* \section LICENSE
|
||||||
|
*
|
||||||
|
* This file is part of the libLTE library.
|
||||||
|
*
|
||||||
|
* libLTE 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 3 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* libLTE 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.
|
||||||
|
*
|
||||||
|
* A copy of the GNU Lesser General Public License can be found in
|
||||||
|
* the LICENSE file in the top-level directory of this distribution
|
||||||
|
* and at http://www.gnu.org/licenses/.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "lte/fec/rm_turbo.h"
|
||||||
|
|
||||||
|
#define NCOLS 32
|
||||||
|
#define NROWS_MAX NCOLS
|
||||||
|
#define RATE 3
|
||||||
|
|
||||||
|
unsigned char RM_PERM_TC[NCOLS] =
|
||||||
|
{ 0, 16, 8, 24, 4, 20, 12, 28, 2, 18, 10, 26, 6, 22, 14, 30, 1, 17, 9,
|
||||||
|
25, 5, 21, 13, 29, 3, 19, 11, 27, 7, 23, 15, 31 };
|
||||||
|
|
||||||
|
int rm_turbo_init(rm_turbo_t *q, int buffer_len) {
|
||||||
|
q->buffer_len = buffer_len;
|
||||||
|
q->buffer = malloc(buffer_len * sizeof(float));
|
||||||
|
if (!q->buffer) {
|
||||||
|
perror("malloc");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
q->d2_perm = malloc(buffer_len * sizeof(int) / 3 + 1);
|
||||||
|
if (!q->d2_perm) {
|
||||||
|
perror("malloc");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rm_turbo_free(rm_turbo_t *q) {
|
||||||
|
if (q->buffer) {
|
||||||
|
free(q->buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Turbo Code Rate Matching.
|
||||||
|
* 3GPP TS 36.212 v10.1.0 section 5.1.4.1
|
||||||
|
*
|
||||||
|
* TODO: Soft buffer size limitation according to UE category
|
||||||
|
*/
|
||||||
|
int rm_turbo_tx(rm_turbo_t *q, char *input, int in_len, char *output, int out_len, int rv_idx) {
|
||||||
|
|
||||||
|
char *tmp = (char*) q->buffer;
|
||||||
|
int nrows, ndummy, K_p;
|
||||||
|
|
||||||
|
int i, j, k, s, kidx, N_cb, k0;
|
||||||
|
|
||||||
|
nrows = (int) (in_len / RATE - 1) / NCOLS + 1;
|
||||||
|
K_p = nrows * NCOLS;
|
||||||
|
if (3 * K_p > q->buffer_len) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"Input too large. Max input length including dummy bits is %d\n",
|
||||||
|
q->buffer_len);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ndummy = K_p - in_len / RATE;
|
||||||
|
if (ndummy < 0) {
|
||||||
|
ndummy = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sub-block interleaver (5.1.4.1.1) and bit collection */
|
||||||
|
k = 0;
|
||||||
|
for (s = 0; s < 2; s++) {
|
||||||
|
for (j = 0; j < NCOLS; j++) {
|
||||||
|
for (i = 0; i < nrows; i++) {
|
||||||
|
if (s == 0) {
|
||||||
|
kidx = k%K_p;
|
||||||
|
} else {
|
||||||
|
kidx = K_p + 2 * (k%K_p);
|
||||||
|
}
|
||||||
|
if (i * NCOLS + RM_PERM_TC[j] < ndummy) {
|
||||||
|
tmp[kidx] = TX_NULL;
|
||||||
|
} else {
|
||||||
|
tmp[kidx] = input[(i * NCOLS + RM_PERM_TC[j] - ndummy) * 3 + s];
|
||||||
|
}
|
||||||
|
k++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// d_k^(2) goes through special permutation
|
||||||
|
for (k = 0; k < K_p; k++) {
|
||||||
|
kidx = (RM_PERM_TC[k / nrows] + NCOLS * (k % nrows) + 1) % K_p;
|
||||||
|
if ((kidx - ndummy) < 0) {
|
||||||
|
tmp[K_p + 2 * k + 1] = TX_NULL;
|
||||||
|
} else {
|
||||||
|
tmp[K_p + 2 * k + 1] = input[3 * (kidx - ndummy) + 2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Bit selection and transmission 5.1.4.1.2 */
|
||||||
|
N_cb = 3 * K_p; // TODO: Soft buffer size limitation
|
||||||
|
|
||||||
|
k0 = nrows * (2 * (int) ceilf((float) N_cb / (float) (8 * nrows))
|
||||||
|
* rv_idx + 2);
|
||||||
|
k = 0;
|
||||||
|
j = 0;
|
||||||
|
|
||||||
|
while (k < out_len) {
|
||||||
|
if (tmp[(k0 + j) % N_cb] != TX_NULL) {
|
||||||
|
output[k] = tmp[(k0 + j) % N_cb];
|
||||||
|
k++;
|
||||||
|
}
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Undoes Turbo Code Rate Matching.
|
||||||
|
* 3GPP TS 36.212 v10.1.0 section 5.1.4.1
|
||||||
|
*/
|
||||||
|
int rm_turbo_rx(rm_turbo_t *q, float *input, int in_len, float *output, int out_len, int rv_idx) {
|
||||||
|
|
||||||
|
int nrows, ndummy, K_p, k0, N_cb, jp, kidx;
|
||||||
|
int i, j, k;
|
||||||
|
int d_i, d_j;
|
||||||
|
bool isdummy;
|
||||||
|
|
||||||
|
float *tmp = (float*) q->buffer;
|
||||||
|
|
||||||
|
nrows = (int) (out_len / RATE - 1) / NCOLS + 1;
|
||||||
|
K_p = nrows * NCOLS;
|
||||||
|
if (3 * K_p > q->buffer_len) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"Input too large. Max input length including dummy bits is %d\n",
|
||||||
|
q->buffer_len);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ndummy = K_p - out_len / RATE;
|
||||||
|
if (ndummy < 0) {
|
||||||
|
ndummy = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < RATE * K_p; i++) {
|
||||||
|
tmp[i] = RX_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Undo bit collection. Account for dummy bits */
|
||||||
|
N_cb = 3 * K_p; // TODO: Soft buffer size limitation
|
||||||
|
k0 = nrows * (2 * (int) ceilf((float) N_cb / (float) (8 * nrows))
|
||||||
|
* rv_idx + 2);
|
||||||
|
k = 0;
|
||||||
|
j = 0;
|
||||||
|
while (k < in_len) {
|
||||||
|
jp = (k0 + j) % N_cb;
|
||||||
|
|
||||||
|
if (jp == 32 || jp == 95 || jp == 0) {
|
||||||
|
i=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (jp < K_p || !(jp%2)) {
|
||||||
|
if (jp >= K_p) {
|
||||||
|
d_i = ((jp-K_p) / 2) / nrows;
|
||||||
|
d_j = ((jp-K_p) / 2) % nrows;
|
||||||
|
} else {
|
||||||
|
d_i = jp / nrows;
|
||||||
|
d_j = jp % nrows;
|
||||||
|
}
|
||||||
|
if (d_j * NCOLS + RM_PERM_TC[d_i] >= ndummy) {
|
||||||
|
isdummy = false;
|
||||||
|
} else {
|
||||||
|
isdummy = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
int jpp = (jp-K_p-1)/2;
|
||||||
|
kidx = (RM_PERM_TC[jpp / nrows] + NCOLS * (jpp % nrows) + 1) % K_p;
|
||||||
|
q->d2_perm[kidx] = jpp; // save the permutation in a temporary buffer
|
||||||
|
if ((kidx - ndummy) < 0) {
|
||||||
|
isdummy = true;
|
||||||
|
} else {
|
||||||
|
isdummy = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isdummy) {
|
||||||
|
if (tmp[jp] == RX_NULL) {
|
||||||
|
tmp[jp] = input[k];
|
||||||
|
} else if (input[k] != RX_NULL) {
|
||||||
|
tmp[jp] += input[k]; /* soft combine LLRs */
|
||||||
|
}
|
||||||
|
k++;
|
||||||
|
}
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* interleaving and bit selection */
|
||||||
|
for (i = 0; i < out_len / RATE; i++) {
|
||||||
|
d_i = (i + ndummy) / NCOLS;
|
||||||
|
d_j = (i + ndummy) % NCOLS;
|
||||||
|
for (j = 0; j < RATE; j++) {
|
||||||
|
if (j != 2) {
|
||||||
|
kidx = K_p * j + (j+1)*(RM_PERM_TC[d_j] * nrows + d_i);
|
||||||
|
} else {
|
||||||
|
// use the saved permuatation function to avoid computing the inverse
|
||||||
|
kidx = 2*q->d2_perm[(i+ndummy)%K_p]+K_p+1;
|
||||||
|
}
|
||||||
|
float o = tmp[kidx];
|
||||||
|
if (o != RX_NULL) {
|
||||||
|
output[i * RATE + j] = o;
|
||||||
|
} else {
|
||||||
|
output[i * RATE + j] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** High-level API */
|
||||||
|
|
||||||
|
int rm_turbo_initialize(rm_turbo_hl* h) {
|
||||||
|
return rm_turbo_init(&h->q, 7000);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** This function can be called in a subframe (1ms) basis */
|
||||||
|
int rm_turbo_work(rm_turbo_hl* hl) {
|
||||||
|
if (hl->init.direction) {
|
||||||
|
rm_turbo_tx(&hl->q, hl->input, hl->in_len, hl->output, hl->ctrl_in.E, hl->ctrl_in.rv_idx);
|
||||||
|
hl->out_len = hl->ctrl_in.E;
|
||||||
|
} else {
|
||||||
|
rm_turbo_rx(&hl->q, hl->input, hl->in_len, hl->output, hl->ctrl_in.S, hl->ctrl_in.rv_idx);
|
||||||
|
hl->out_len = hl->ctrl_in.S;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rm_turbo_stop(rm_turbo_hl* hl) {
|
||||||
|
rm_turbo_free(&hl->q);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,117 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* \section COPYRIGHT
|
||||||
|
*
|
||||||
|
* Copyright 2013-2014 The libLTE Developers. See the
|
||||||
|
* COPYRIGHT file at the top-level directory of this distribution.
|
||||||
|
*
|
||||||
|
* \section LICENSE
|
||||||
|
*
|
||||||
|
* This file is part of the libLTE library.
|
||||||
|
*
|
||||||
|
* libLTE 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 3 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* libLTE 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.
|
||||||
|
*
|
||||||
|
* A copy of the GNU Lesser General Public License can be found in
|
||||||
|
* the LICENSE file in the top-level directory of this distribution
|
||||||
|
* and at http://www.gnu.org/licenses/.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "lte/common/base.h"
|
||||||
|
#include "lte/fec/tc_interl.h"
|
||||||
|
#include "lte/fec/turbocoder.h"
|
||||||
|
#include "lte/utils/debug.h"
|
||||||
|
|
||||||
|
/************************************************
|
||||||
|
*
|
||||||
|
* LTE TURBO CODE INTERLEAVER
|
||||||
|
*
|
||||||
|
************************************************/
|
||||||
|
|
||||||
|
const int f1_list[NOF_TC_CB_SIZES] = { 3, 7, 19, 7, 7, 11, 5, 11, 7, 41, 103, 15, 9, 17,
|
||||||
|
9, 21, 101, 21, 57, 23, 13, 27, 11, 27, 85, 29, 33, 15, 17, 33, 103, 19,
|
||||||
|
19, 37, 19, 21, 21, 115, 193, 21, 133, 81, 45, 23, 243, 151, 155, 25,
|
||||||
|
51, 47, 91, 29, 29, 247, 29, 89, 91, 157, 55, 31, 17, 35, 227, 65, 19,
|
||||||
|
37, 41, 39, 185, 43, 21, 155, 79, 139, 23, 217, 25, 17, 127, 25, 239,
|
||||||
|
17, 137, 215, 29, 15, 147, 29, 59, 65, 55, 31, 17, 171, 67, 35, 19, 39,
|
||||||
|
19, 199, 21, 211, 21, 43, 149, 45, 49, 71, 13, 17, 25, 183, 55, 127, 27,
|
||||||
|
29, 29, 57, 45, 31, 59, 185, 113, 31, 17, 171, 209, 253, 367, 265, 181,
|
||||||
|
39, 27, 127, 143, 43, 29, 45, 157, 47, 13, 111, 443, 51, 51, 451, 257,
|
||||||
|
57, 313, 271, 179, 331, 363, 375, 127, 31, 33, 43, 33, 477, 35, 233,
|
||||||
|
357, 337, 37, 71, 71, 37, 39, 127, 39, 39, 31, 113, 41, 251, 43, 21, 43,
|
||||||
|
45, 45, 161, 89, 323, 47, 23, 47, 263 };
|
||||||
|
|
||||||
|
const int f2_list[NOF_TC_CB_SIZES] = { 10, 12, 42, 16, 18, 20, 22, 24, 26, 84, 90, 32,
|
||||||
|
34, 108, 38, 120, 84, 44, 46, 48, 50, 52, 36, 56, 58, 60, 62, 32, 198,
|
||||||
|
68, 210, 36, 74, 76, 78, 120, 82, 84, 86, 44, 90, 46, 94, 48, 98, 40,
|
||||||
|
102, 52, 106, 72, 110, 168, 114, 58, 118, 180, 122, 62, 84, 64, 66, 68,
|
||||||
|
420, 96, 74, 76, 234, 80, 82, 252, 86, 44, 120, 92, 94, 48, 98, 80, 102,
|
||||||
|
52, 106, 48, 110, 112, 114, 58, 118, 60, 122, 124, 84, 64, 66, 204, 140,
|
||||||
|
72, 74, 76, 78, 240, 82, 252, 86, 88, 60, 92, 846, 48, 28, 80, 102, 104,
|
||||||
|
954, 96, 110, 112, 114, 116, 354, 120, 610, 124, 420, 64, 66, 136, 420,
|
||||||
|
216, 444, 456, 468, 80, 164, 504, 172, 88, 300, 92, 188, 96, 28, 240,
|
||||||
|
204, 104, 212, 192, 220, 336, 228, 232, 236, 120, 244, 248, 168, 64,
|
||||||
|
130, 264, 134, 408, 138, 280, 142, 480, 146, 444, 120, 152, 462, 234,
|
||||||
|
158, 80, 96, 902, 166, 336, 170, 86, 174, 176, 178, 120, 182, 184, 186,
|
||||||
|
94, 190, 480 };
|
||||||
|
|
||||||
|
int tc_interl_LTE_init(tc_interl_t *h, int long_cb) {
|
||||||
|
int cb_table_idx, f1, f2;
|
||||||
|
unsigned long long i, j;
|
||||||
|
|
||||||
|
cb_table_idx = lte_find_cb_index(long_cb);
|
||||||
|
if (cb_table_idx == -1) {
|
||||||
|
fprintf(stderr, "Can't find long_cb=%d in valid TC CB table\n", long_cb);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
h->forward = h->reverse = NULL;
|
||||||
|
h->forward = malloc(sizeof(int) * (long_cb));
|
||||||
|
if (!h->forward) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
h->reverse = malloc(sizeof(int) * (long_cb));
|
||||||
|
if (!h->reverse) {
|
||||||
|
perror("malloc");
|
||||||
|
free(h->forward);
|
||||||
|
h->forward = h->reverse = NULL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
f1 = f1_list[cb_table_idx];
|
||||||
|
f2 = f2_list[cb_table_idx];
|
||||||
|
|
||||||
|
DEBUG("table_idx: %d, f1: %d, f2: %d\n", cb_table_idx, f1, f2);
|
||||||
|
|
||||||
|
h->forward[0] = 0;
|
||||||
|
h->reverse[0] = 0;
|
||||||
|
for (i = 1; i < long_cb; i++) {
|
||||||
|
j = (f1*i + f2*i*i) % (long_cb);
|
||||||
|
h->forward[i] = j;
|
||||||
|
h->reverse[j] = i;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,257 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* \section COPYRIGHT
|
||||||
|
*
|
||||||
|
* Copyright 2013-2014 The libLTE Developers. See the
|
||||||
|
* COPYRIGHT file at the top-level directory of this distribution.
|
||||||
|
*
|
||||||
|
* \section LICENSE
|
||||||
|
*
|
||||||
|
* This file is part of the libLTE library.
|
||||||
|
*
|
||||||
|
* libLTE 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 3 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* libLTE 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.
|
||||||
|
*
|
||||||
|
* A copy of the GNU Lesser General Public License can be found in
|
||||||
|
* the LICENSE file in the top-level directory of this distribution
|
||||||
|
* and at http://www.gnu.org/licenses/.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "lte/fec/tc_interl.h"
|
||||||
|
#include "lte/fec/turbocoder.h"
|
||||||
|
|
||||||
|
#define TURBO_RATE 3
|
||||||
|
|
||||||
|
int mcd(int x, int y);
|
||||||
|
|
||||||
|
/************************************************
|
||||||
|
*
|
||||||
|
* UMTS TURBO CODE INTERLEAVER
|
||||||
|
*
|
||||||
|
************************************************/
|
||||||
|
|
||||||
|
#define MAX_ROWS 20
|
||||||
|
#define MAX_COLS 256
|
||||||
|
|
||||||
|
const unsigned short table_p[52] = { 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43,
|
||||||
|
47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113,
|
||||||
|
127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193,
|
||||||
|
197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257 };
|
||||||
|
const unsigned char table_v[52] = { 3, 2, 2, 3, 2, 5, 2, 3, 2, 6, 3, 5, 2, 2, 2,
|
||||||
|
2, 7, 5, 3, 2, 3, 5, 2, 5, 2, 6, 3, 3, 2, 3, 2, 2, 6, 5, 2, 5, 2, 2, 2,
|
||||||
|
19, 5, 2, 3, 2, 3, 2, 6, 3, 7, 7, 6, 3 };
|
||||||
|
|
||||||
|
void tc_interl_free(tc_interl_t *h) {
|
||||||
|
if (h->forward) {
|
||||||
|
free(h->forward);
|
||||||
|
}
|
||||||
|
if (h->reverse) {
|
||||||
|
free(h->reverse);
|
||||||
|
}
|
||||||
|
h->forward = h->reverse = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tc_interl_UMTS_init(tc_interl_t *h, int long_cb) {
|
||||||
|
|
||||||
|
int i, j;
|
||||||
|
int res, prim, aux;
|
||||||
|
int kp, k;
|
||||||
|
int *per, *desper;
|
||||||
|
unsigned char v;
|
||||||
|
unsigned short p;
|
||||||
|
unsigned short s[MAX_COLS], q[MAX_ROWS], r[MAX_ROWS], T[MAX_ROWS];
|
||||||
|
unsigned short U[MAX_COLS * MAX_ROWS];
|
||||||
|
int M_Rows, M_Cols, M_long;
|
||||||
|
|
||||||
|
h->forward = h->reverse = NULL;
|
||||||
|
h->forward = malloc(sizeof(int) * (long_cb));
|
||||||
|
if (!h->forward) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
h->reverse = malloc(sizeof(int) * (long_cb));
|
||||||
|
if (!h->reverse) {
|
||||||
|
perror("malloc");
|
||||||
|
free(h->forward);
|
||||||
|
h->forward = h->reverse = NULL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
M_long = long_cb;
|
||||||
|
|
||||||
|
/* Find R*/
|
||||||
|
if ((40 <= M_long) && (M_long <= 159))
|
||||||
|
M_Rows = 5;
|
||||||
|
else if (((160 <= M_long) && (M_long <= 200))
|
||||||
|
|| ((481 <= M_long) && (M_long <= 530)))
|
||||||
|
M_Rows = 10;
|
||||||
|
else
|
||||||
|
M_Rows = 20;
|
||||||
|
|
||||||
|
/* Find p i v*/
|
||||||
|
if ((481 <= M_long) && (M_long <= 530)) {
|
||||||
|
p = 53;
|
||||||
|
v = 2;
|
||||||
|
M_Cols = p;
|
||||||
|
} else {
|
||||||
|
i = 0;
|
||||||
|
do {
|
||||||
|
p = table_p[i];
|
||||||
|
v = table_v[i];
|
||||||
|
i++;
|
||||||
|
} while (M_long > (M_Rows * (p + 1)));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Find C*/
|
||||||
|
if ((M_long) <= (M_Rows) * ((p) - 1))
|
||||||
|
M_Cols = (p) - 1;
|
||||||
|
else if (((M_Rows) * (p - 1) < M_long) && (M_long <= (M_Rows) * (p)))
|
||||||
|
M_Cols = p;
|
||||||
|
else if ((M_Rows) * (p) < M_long)
|
||||||
|
M_Cols = (p) + 1;
|
||||||
|
|
||||||
|
q[0] = 1;
|
||||||
|
prim = 6;
|
||||||
|
|
||||||
|
for (i = 1; i < M_Rows; i++) {
|
||||||
|
do {
|
||||||
|
prim++;
|
||||||
|
res = mcd(prim, p - 1);
|
||||||
|
} while (res != 1);
|
||||||
|
q[i] = prim;
|
||||||
|
}
|
||||||
|
|
||||||
|
s[0] = 1;
|
||||||
|
for (i = 1; i < p - 1; i++) {
|
||||||
|
s[i] = (v * s[i - 1]) % p;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (M_long <= 159 && M_long >= 40) {
|
||||||
|
T[0] = 4;
|
||||||
|
T[1] = 3;
|
||||||
|
T[2] = 2;
|
||||||
|
T[3] = 1;
|
||||||
|
T[4] = 0;
|
||||||
|
} else if ((M_long <= 200 && M_long >= 160)
|
||||||
|
|| (M_long <= 530 && M_long >= 481)) {
|
||||||
|
T[0] = 9;
|
||||||
|
T[1] = 8;
|
||||||
|
T[2] = 7;
|
||||||
|
T[3] = 6;
|
||||||
|
T[4] = 5;
|
||||||
|
T[5] = 4;
|
||||||
|
T[6] = 3;
|
||||||
|
T[7] = 2;
|
||||||
|
T[8] = 1;
|
||||||
|
T[9] = 0;
|
||||||
|
} else if ((M_long <= 2480 && M_long >= 2281)
|
||||||
|
|| (M_long <= 3210 && M_long >= 3161)) {
|
||||||
|
T[0] = 19;
|
||||||
|
T[1] = 9;
|
||||||
|
T[2] = 14;
|
||||||
|
T[3] = 4;
|
||||||
|
T[4] = 0;
|
||||||
|
T[5] = 2;
|
||||||
|
T[6] = 5;
|
||||||
|
T[7] = 7;
|
||||||
|
T[8] = 12;
|
||||||
|
T[9] = 18;
|
||||||
|
T[10] = 16;
|
||||||
|
T[11] = 13;
|
||||||
|
T[12] = 17;
|
||||||
|
T[13] = 15;
|
||||||
|
T[14] = 3;
|
||||||
|
T[15] = 1;
|
||||||
|
T[16] = 6;
|
||||||
|
T[17] = 11;
|
||||||
|
T[18] = 8;
|
||||||
|
T[19] = 10;
|
||||||
|
} else {
|
||||||
|
T[0] = 19;
|
||||||
|
T[1] = 9;
|
||||||
|
T[2] = 14;
|
||||||
|
T[3] = 4;
|
||||||
|
T[4] = 0;
|
||||||
|
T[5] = 2;
|
||||||
|
T[6] = 5;
|
||||||
|
T[7] = 7;
|
||||||
|
T[8] = 12;
|
||||||
|
T[9] = 18;
|
||||||
|
T[10] = 10;
|
||||||
|
T[11] = 8;
|
||||||
|
T[12] = 13;
|
||||||
|
T[13] = 17;
|
||||||
|
T[14] = 3;
|
||||||
|
T[15] = 1;
|
||||||
|
T[16] = 16;
|
||||||
|
T[17] = 6;
|
||||||
|
T[18] = 15;
|
||||||
|
T[19] = 11;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < M_Rows; i++) {
|
||||||
|
r[T[i]] = q[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < M_Rows; i++) {
|
||||||
|
for (j = 0; j < p - 1; j++) {
|
||||||
|
U[i * M_Cols + j] = s[(j * r[i]) % (p - 1)];
|
||||||
|
if (M_Cols == (p - 1))
|
||||||
|
U[i * M_Cols + j] -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (M_Cols == p) {
|
||||||
|
for (i = 0; i < M_Rows; i++)
|
||||||
|
U[i * M_Cols + p - 1] = 0;
|
||||||
|
} else if (M_Cols == p + 1) {
|
||||||
|
for (i = 0; i < M_Rows; i++) {
|
||||||
|
U[i * M_Cols + p - 1] = 0;
|
||||||
|
U[i * M_Cols + p] = p;
|
||||||
|
}
|
||||||
|
if (M_long == M_Cols * M_Rows) {
|
||||||
|
aux = U[(M_Rows - 1) * M_Cols + p];
|
||||||
|
U[(M_Rows - 1) * M_Cols + p] = U[(M_Rows - 1) * M_Cols + 0];
|
||||||
|
U[(M_Rows - 1) * M_Cols + 0] = aux;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
per = h->forward;
|
||||||
|
desper = h->reverse;
|
||||||
|
|
||||||
|
k = 0;
|
||||||
|
for (j = 0; j < M_Cols; j++) {
|
||||||
|
for (i = 0; i < M_Rows; i++) {
|
||||||
|
kp = T[i] * M_Cols + U[i * M_Cols + j];
|
||||||
|
if (kp < M_long) {
|
||||||
|
desper[kp] = k;
|
||||||
|
per[k] = kp;
|
||||||
|
k++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int mcd(int x, int y) {
|
||||||
|
int r = 1;
|
||||||
|
|
||||||
|
while (r) {
|
||||||
|
r = x % y;
|
||||||
|
x = y;
|
||||||
|
y = r;
|
||||||
|
}
|
||||||
|
return x;
|
||||||
|
}
|
@ -0,0 +1,134 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* \section COPYRIGHT
|
||||||
|
*
|
||||||
|
* Copyright 2013-2014 The libLTE Developers. See the
|
||||||
|
* COPYRIGHT file at the top-level directory of this distribution.
|
||||||
|
*
|
||||||
|
* \section LICENSE
|
||||||
|
*
|
||||||
|
* This file is part of the libLTE library.
|
||||||
|
*
|
||||||
|
* libLTE 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 3 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* libLTE 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.
|
||||||
|
*
|
||||||
|
* A copy of the GNU Lesser General Public License can be found in
|
||||||
|
* the LICENSE file in the top-level directory of this distribution
|
||||||
|
* and at http://www.gnu.org/licenses/.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "lte/fec/tc_interl.h"
|
||||||
|
#include "lte/fec/turbocoder.h"
|
||||||
|
|
||||||
|
#define NOF_REGS 3
|
||||||
|
|
||||||
|
int tcod_init(tcod_t *h, int long_cb) {
|
||||||
|
|
||||||
|
if (tc_interl_LTE_init(&h->interl, long_cb)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
h->long_cb = long_cb;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void tcod_free(tcod_t *h) {
|
||||||
|
tc_interl_free(&h->interl);
|
||||||
|
h->long_cb = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void tcod_encode(tcod_t *h, char *input, char *output) {
|
||||||
|
|
||||||
|
char reg1_0,reg1_1,reg1_2, reg2_0,reg2_1,reg2_2;
|
||||||
|
int i,k=0,j;
|
||||||
|
char bit;
|
||||||
|
char in,out;
|
||||||
|
int *per;
|
||||||
|
|
||||||
|
per=h->interl.forward;
|
||||||
|
|
||||||
|
reg1_0=0;
|
||||||
|
reg1_1=0;
|
||||||
|
reg1_2=0;
|
||||||
|
|
||||||
|
reg2_0=0;
|
||||||
|
reg2_1=0;
|
||||||
|
reg2_2=0;
|
||||||
|
|
||||||
|
k=0;
|
||||||
|
for (i=0;i<h->long_cb;i++) {
|
||||||
|
bit=input[i];
|
||||||
|
|
||||||
|
output[k]=bit;
|
||||||
|
k++;
|
||||||
|
|
||||||
|
in=bit^(reg1_2^reg1_1);
|
||||||
|
out=reg1_2^(reg1_0^in);
|
||||||
|
|
||||||
|
reg1_2=reg1_1;
|
||||||
|
reg1_1=reg1_0;
|
||||||
|
reg1_0=in;
|
||||||
|
|
||||||
|
output[k]=out;
|
||||||
|
k++;
|
||||||
|
|
||||||
|
bit=input[per[i]];
|
||||||
|
|
||||||
|
in=bit^(reg2_2^reg2_1);
|
||||||
|
out=reg2_2^(reg2_0^in);
|
||||||
|
|
||||||
|
reg2_2=reg2_1;
|
||||||
|
reg2_1=reg2_0;
|
||||||
|
reg2_0=in;
|
||||||
|
|
||||||
|
output[k]=out;
|
||||||
|
k++;
|
||||||
|
}
|
||||||
|
|
||||||
|
k=3*h->long_cb;
|
||||||
|
|
||||||
|
/* TAILING CODER #1 */
|
||||||
|
for (j=0;j<NOF_REGS;j++) {
|
||||||
|
bit=reg1_2^reg1_1;
|
||||||
|
|
||||||
|
output[k]=bit;
|
||||||
|
k++;
|
||||||
|
|
||||||
|
in=bit^(reg1_2^reg1_1);
|
||||||
|
out=reg1_2^(reg1_0^in);
|
||||||
|
|
||||||
|
reg1_2=reg1_1;
|
||||||
|
reg1_1=reg1_0;
|
||||||
|
reg1_0=in;
|
||||||
|
|
||||||
|
output[k]=out;
|
||||||
|
k++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TAILING CODER #2 */
|
||||||
|
for (j=0;j<NOF_REGS;j++) {
|
||||||
|
bit=reg2_2^reg2_1;
|
||||||
|
|
||||||
|
output[k]=bit;
|
||||||
|
k++;
|
||||||
|
|
||||||
|
in=bit^(reg2_2^reg2_1);
|
||||||
|
out=reg2_2^(reg2_0^in);
|
||||||
|
|
||||||
|
reg2_2=reg2_1;
|
||||||
|
reg2_1=reg2_0;
|
||||||
|
reg2_0=in;
|
||||||
|
|
||||||
|
output[k]=out;
|
||||||
|
k++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,299 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <strings.h>
|
||||||
|
|
||||||
|
#include "lte/fec/tc_interl.h"
|
||||||
|
#include "lte/fec/turbodecoder.h"
|
||||||
|
|
||||||
|
/************************************************
|
||||||
|
*
|
||||||
|
* MAP_GEN is the MAX-LOG-MAP generic implementation of the
|
||||||
|
* Decoder
|
||||||
|
*
|
||||||
|
************************************************/
|
||||||
|
void map_gen_beta(map_gen_t *s, llr_t *input, llr_t *parity) {
|
||||||
|
llr_t m_b[8], new[8], old[8];
|
||||||
|
llr_t x, y, xy;
|
||||||
|
int k;
|
||||||
|
int end = s->long_cb + RATE;
|
||||||
|
llr_t *beta = s->beta;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i=0;i<8;i++) {
|
||||||
|
old[i] = beta[8 * (end) + i];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (k = end - 1; k >= 0; k--) {
|
||||||
|
x = input[k];
|
||||||
|
y = parity[k];
|
||||||
|
|
||||||
|
xy = x + y;
|
||||||
|
|
||||||
|
m_b[0] = old[4] + xy;
|
||||||
|
m_b[1] = old[4];
|
||||||
|
m_b[2] = old[5] + y;
|
||||||
|
m_b[3] = old[5] + x;
|
||||||
|
m_b[4] = old[6] + x;
|
||||||
|
m_b[5] = old[6] + y;
|
||||||
|
m_b[6] = old[7];
|
||||||
|
m_b[7] = old[7] + xy;
|
||||||
|
|
||||||
|
new[0] = old[0];
|
||||||
|
new[1] = old[0] + xy;
|
||||||
|
new[2] = old[1] + x;
|
||||||
|
new[3] = old[1] + y;
|
||||||
|
new[4] = old[2] + y;
|
||||||
|
new[5] = old[2] + x;
|
||||||
|
new[6] = old[3] + xy;
|
||||||
|
new[7] = old[3];
|
||||||
|
|
||||||
|
for (i=0;i<8;i++) {
|
||||||
|
if (m_b[i] > new[i])
|
||||||
|
new[i] = m_b[i];
|
||||||
|
beta[8 * k + i] = new[i];
|
||||||
|
old[i] = new[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void map_gen_alpha(map_gen_t *s, llr_t *input, llr_t *parity, llr_t *output) {
|
||||||
|
llr_t m_b[8], new[8], old[8], max1[8], max0[8];
|
||||||
|
llr_t m1, m0;
|
||||||
|
llr_t x, y, xy;
|
||||||
|
llr_t out;
|
||||||
|
int k;
|
||||||
|
int end = s->long_cb;
|
||||||
|
llr_t *beta = s->beta;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
old[0] = 0;
|
||||||
|
for (i=1;i<8;i++) {
|
||||||
|
old[i] = -INF;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (k = 1; k < end + 1; k++) {
|
||||||
|
x = input[k - 1];
|
||||||
|
y = parity[k - 1];
|
||||||
|
|
||||||
|
xy = x + y;
|
||||||
|
|
||||||
|
m_b[0] = old[0];
|
||||||
|
m_b[1] = old[3] + y;
|
||||||
|
m_b[2] = old[4] + y;
|
||||||
|
m_b[3] = old[7];
|
||||||
|
m_b[4] = old[1];
|
||||||
|
m_b[5] = old[2] + y;
|
||||||
|
m_b[6] = old[5] + y;
|
||||||
|
m_b[7] = old[6];
|
||||||
|
|
||||||
|
new[0] = old[1] + xy;
|
||||||
|
new[1] = old[2] + x;
|
||||||
|
new[2] = old[5] + x;
|
||||||
|
new[3] = old[6] + xy;
|
||||||
|
new[4] = old[0] + xy;
|
||||||
|
new[5] = old[3] + x;
|
||||||
|
new[6] = old[4] + x;
|
||||||
|
new[7] = old[7] + xy;
|
||||||
|
|
||||||
|
for (i=0;i<8;i++) {
|
||||||
|
max0[i] = m_b[i] + beta[8 * k + i];
|
||||||
|
max1[i] = new[i] + beta[8 * k + i];
|
||||||
|
}
|
||||||
|
|
||||||
|
m1 = max1[0];
|
||||||
|
m0 = max0[0];
|
||||||
|
|
||||||
|
for (i=1;i<8;i++) {
|
||||||
|
if (max1[i] > m1)
|
||||||
|
m1 = max1[i];
|
||||||
|
if (max0[i] > m0)
|
||||||
|
m0 = max0[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i=0;i<8;i++) {
|
||||||
|
if (m_b[i] > new[i])
|
||||||
|
new[i] = m_b[i];
|
||||||
|
old[i] = new[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
out = m1 - m0;
|
||||||
|
output[k - 1] = out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int map_gen_init(map_gen_t *h, int long_cb) {
|
||||||
|
bzero(h, sizeof(map_gen_t));
|
||||||
|
h->beta = malloc(sizeof(llr_t) * (long_cb + TOTALTAIL + 1)* NUMSTATES);
|
||||||
|
if (!h->beta) {
|
||||||
|
perror("malloc");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
h->long_cb = long_cb;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void map_gen_free(map_gen_t *h) {
|
||||||
|
if (h->beta) {
|
||||||
|
free(h->beta);
|
||||||
|
}
|
||||||
|
bzero(h, sizeof(map_gen_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
void map_gen_dec(map_gen_t *h, llr_t *input, llr_t *parity, llr_t *output) {
|
||||||
|
int k;
|
||||||
|
|
||||||
|
h->beta[(h->long_cb + TAIL) * NUMSTATES] = 0;
|
||||||
|
for (k = 1; k < NUMSTATES; k++)
|
||||||
|
h->beta[(h->long_cb + TAIL) * NUMSTATES + k] = -INF;
|
||||||
|
|
||||||
|
map_gen_beta(h, input, parity);
|
||||||
|
map_gen_alpha(h, input, parity, output);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/************************************************
|
||||||
|
*
|
||||||
|
* TURBO DECODER INTERFACE
|
||||||
|
*
|
||||||
|
************************************************/
|
||||||
|
int tdec_init(tdec_t *h, int long_cb) {
|
||||||
|
int ret = -1;
|
||||||
|
bzero(h, sizeof(tdec_t));
|
||||||
|
int len = long_cb + TOTALTAIL;
|
||||||
|
|
||||||
|
h->llr1 = malloc(sizeof(llr_t) * len);
|
||||||
|
if (!h->llr1) {
|
||||||
|
perror("malloc");
|
||||||
|
goto clean_and_exit;
|
||||||
|
}
|
||||||
|
h->llr2 = malloc(sizeof(llr_t) * len);
|
||||||
|
if (!h->llr2) {
|
||||||
|
perror("malloc");
|
||||||
|
goto clean_and_exit;
|
||||||
|
}
|
||||||
|
h->w = malloc(sizeof(llr_t) * len);
|
||||||
|
if (!h->w) {
|
||||||
|
perror("malloc");
|
||||||
|
goto clean_and_exit;
|
||||||
|
}
|
||||||
|
h->syst = malloc(sizeof(llr_t) * len);
|
||||||
|
if (!h->syst) {
|
||||||
|
perror("malloc");
|
||||||
|
goto clean_and_exit;
|
||||||
|
}
|
||||||
|
h->parity = malloc(sizeof(llr_t) * len);
|
||||||
|
if (!h->parity) {
|
||||||
|
perror("malloc");
|
||||||
|
goto clean_and_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (map_gen_init(&h->dec, long_cb)) {
|
||||||
|
goto clean_and_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
h->long_cb = long_cb;
|
||||||
|
|
||||||
|
if (tc_interl_LTE_init(&h->interleaver, h->long_cb) < 0) {
|
||||||
|
goto clean_and_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
clean_and_exit:
|
||||||
|
if (ret == -1) {
|
||||||
|
tdec_free(h);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void tdec_free(tdec_t *h) {
|
||||||
|
if (h->llr1) {
|
||||||
|
free(h->llr1);
|
||||||
|
}
|
||||||
|
if (h->llr2) {
|
||||||
|
free(h->llr2);
|
||||||
|
}
|
||||||
|
if (h->w) {
|
||||||
|
free(h->w);
|
||||||
|
}
|
||||||
|
if (h->syst) {
|
||||||
|
free(h->syst);
|
||||||
|
}
|
||||||
|
if (h->parity) {
|
||||||
|
free(h->parity);
|
||||||
|
}
|
||||||
|
|
||||||
|
map_gen_free(&h->dec);
|
||||||
|
|
||||||
|
tc_interl_free(&h->interleaver);
|
||||||
|
|
||||||
|
bzero(h, sizeof(tdec_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
void tdec_iteration(tdec_t *h, llr_t *input) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
// Prepare systematic and parity bits for MAP DEC #1
|
||||||
|
for (i = 0; i < h->long_cb; i++) {
|
||||||
|
h->syst[i] = input[RATE * i] + h->w[i];
|
||||||
|
h->parity[i] = input[RATE * i + 1];
|
||||||
|
}
|
||||||
|
for (i=h->long_cb;i<h->long_cb+RATE;i++) {
|
||||||
|
h->syst[i] = input[RATE * h->long_cb + NINPUTS * (i - h->long_cb)];
|
||||||
|
h->parity[i] = input[RATE * h->long_cb + NINPUTS * (i - h->long_cb) + 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run MAP DEC #1
|
||||||
|
map_gen_dec(&h->dec, h->syst, h->parity, h->llr1);
|
||||||
|
|
||||||
|
// Prepare systematic and parity bits for MAP DEC #1
|
||||||
|
for (i = 0; i < h->long_cb; i++) {
|
||||||
|
h->syst[i] = h->llr1[h->interleaver.forward[i]] - h->w[h->interleaver.forward[i]];
|
||||||
|
h->parity[i] = input[RATE * i + 2];
|
||||||
|
}
|
||||||
|
for (i=h->long_cb;i<h->long_cb+RATE;i++) {
|
||||||
|
h->syst[i] = input[RATE * h->long_cb + NINPUTS * RATE + NINPUTS * (i - h->long_cb)];
|
||||||
|
h->parity[i] = input[RATE * h->long_cb + NINPUTS * RATE + NINPUTS * (i - h->long_cb) + 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run MAP DEC #1
|
||||||
|
map_gen_dec(&h->dec, h->syst, h->parity, h->llr2);
|
||||||
|
|
||||||
|
// Update a-priori LLR from the last iteration
|
||||||
|
for (i = 0; i < h->long_cb; i++) {
|
||||||
|
h->w[i] += h->llr2[h->interleaver.reverse[i]] - h->llr1[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void tdec_reset(tdec_t *h) {
|
||||||
|
memset(h->w, 0, sizeof(llr_t) * h->long_cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tdec_decision(tdec_t *h, char *output) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < h->long_cb; i++) {
|
||||||
|
output[i] = (h->llr2[h->interleaver.reverse[i]] > 0) ? 1 : 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void tdec_run_all(tdec_t *h, llr_t *input, char *output, int nof_iterations) {
|
||||||
|
int iter = 0;
|
||||||
|
|
||||||
|
tdec_reset(h);
|
||||||
|
|
||||||
|
do {
|
||||||
|
tdec_iteration(h, input);
|
||||||
|
iter++;
|
||||||
|
} while (iter < nof_iterations);
|
||||||
|
|
||||||
|
tdec_decision(h, output);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,142 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* \section COPYRIGHT
|
||||||
|
*
|
||||||
|
* Copyright 2013-2014 The libLTE Developers. See the
|
||||||
|
* COPYRIGHT file at the top-level directory of this distribution.
|
||||||
|
*
|
||||||
|
* \section LICENSE
|
||||||
|
*
|
||||||
|
* This file is part of the libLTE library.
|
||||||
|
*
|
||||||
|
* libLTE 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 3 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* libLTE 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.
|
||||||
|
*
|
||||||
|
* A copy of the GNU Lesser General Public License can be found in
|
||||||
|
* the LICENSE file in the top-level directory of this distribution
|
||||||
|
* and at http://www.gnu.org/licenses/.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <strings.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include "lte.h"
|
||||||
|
|
||||||
|
int nof_tx_bits=-1, nof_rx_bits=-1;
|
||||||
|
int rv_idx = 0;
|
||||||
|
|
||||||
|
void usage(char *prog) {
|
||||||
|
printf("Usage: %s -t nof_tx_bits -r nof_rx_bits [-i rv_idx]\n", prog);
|
||||||
|
}
|
||||||
|
|
||||||
|
void parse_args(int argc, char **argv) {
|
||||||
|
int opt;
|
||||||
|
while ((opt = getopt(argc, argv, "tri")) != -1) {
|
||||||
|
switch (opt) {
|
||||||
|
case 't':
|
||||||
|
nof_tx_bits = atoi(argv[optind]);
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
nof_rx_bits = atoi(argv[optind]);
|
||||||
|
break;
|
||||||
|
case 'i':
|
||||||
|
rv_idx = atoi(argv[optind]);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
usage(argv[0]);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (nof_tx_bits == -1) {
|
||||||
|
usage(argv[0]);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
if (nof_rx_bits == -1) {
|
||||||
|
usage(argv[0]);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
int i;
|
||||||
|
char *bits, *rm_bits;
|
||||||
|
float *rm_symbols, *unrm_symbols;
|
||||||
|
int nof_errors;
|
||||||
|
rm_turbo_t rm_turbo;
|
||||||
|
|
||||||
|
parse_args(argc, argv);
|
||||||
|
|
||||||
|
bits = malloc(sizeof(char) * nof_tx_bits);
|
||||||
|
if (!bits) {
|
||||||
|
perror("malloc");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
rm_bits = malloc(sizeof(char) * nof_rx_bits);
|
||||||
|
if (!rm_bits) {
|
||||||
|
perror("malloc");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
rm_symbols = malloc(sizeof(float) * nof_rx_bits);
|
||||||
|
if (!rm_symbols) {
|
||||||
|
perror("malloc");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
unrm_symbols = malloc(sizeof(float) * nof_tx_bits);
|
||||||
|
if (!unrm_symbols) {
|
||||||
|
perror("malloc");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i=0;i<nof_tx_bits;i++) {
|
||||||
|
bits[i] = rand()%2;
|
||||||
|
}
|
||||||
|
|
||||||
|
rm_turbo_init(&rm_turbo, 1000);
|
||||||
|
|
||||||
|
rm_turbo_tx(&rm_turbo, bits, nof_tx_bits, rm_bits, nof_rx_bits, rv_idx);
|
||||||
|
|
||||||
|
for (i=0;i<nof_rx_bits;i++) {
|
||||||
|
rm_symbols[i] = (float) rm_bits[i]?1:-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
rm_turbo_rx(&rm_turbo, rm_symbols, nof_rx_bits, unrm_symbols, nof_tx_bits, rv_idx);
|
||||||
|
|
||||||
|
nof_errors = 0;
|
||||||
|
for (i=0;i<nof_tx_bits;i++) {
|
||||||
|
if ((unrm_symbols[i] > 0) != bits[i]) {
|
||||||
|
nof_errors++;
|
||||||
|
printf("%.2f != %d\n", unrm_symbols[i], bits[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rm_turbo_free(&rm_turbo);
|
||||||
|
|
||||||
|
free(bits);
|
||||||
|
free(rm_bits);
|
||||||
|
free(rm_symbols);
|
||||||
|
free(unrm_symbols);
|
||||||
|
|
||||||
|
if (nof_tx_bits >= nof_rx_bits) {
|
||||||
|
if (nof_errors) {
|
||||||
|
printf("nof_errors=%d\n", nof_errors);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Ok\n");
|
||||||
|
exit(0);
|
||||||
|
}
|
@ -0,0 +1,324 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* \section COPYRIGHT
|
||||||
|
*
|
||||||
|
* Copyright 2013-2014 The libLTE Developers. See the
|
||||||
|
* COPYRIGHT file at the top-level directory of this distribution.
|
||||||
|
*
|
||||||
|
* \section LICENSE
|
||||||
|
*
|
||||||
|
* This file is part of the libLTE library.
|
||||||
|
*
|
||||||
|
* libLTE 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 3 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* libLTE 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.
|
||||||
|
*
|
||||||
|
* A copy of the GNU Lesser General Public License can be found in
|
||||||
|
* the LICENSE file in the top-level directory of this distribution
|
||||||
|
* and at http://www.gnu.org/licenses/.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <strings.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include "lte.h"
|
||||||
|
|
||||||
|
#include "turbocoder_test.h"
|
||||||
|
|
||||||
|
typedef _Complex float cf_t;
|
||||||
|
|
||||||
|
int frame_length = 1000, nof_frames=100;
|
||||||
|
float ebno_db = 100.0;
|
||||||
|
unsigned int seed = 0;
|
||||||
|
int K = -1;
|
||||||
|
|
||||||
|
#define MAX_ITERATIONS 4
|
||||||
|
int nof_iterations = MAX_ITERATIONS;
|
||||||
|
int test_known_data = 0;
|
||||||
|
int test_errors = 0;
|
||||||
|
|
||||||
|
#define SNR_POINTS 8
|
||||||
|
#define SNR_MIN 0.0
|
||||||
|
#define SNR_MAX 4.0
|
||||||
|
|
||||||
|
void usage(char *prog) {
|
||||||
|
printf("Usage: %s [nlesv]\n", prog);
|
||||||
|
printf("\t-k Test with known data (ignores frame_length) [Default disabled]\n");
|
||||||
|
printf("\t-i nof_iterations [Default %d]\n", nof_iterations);
|
||||||
|
printf("\t-n nof_frames [Default %d]\n", nof_frames);
|
||||||
|
printf("\t-l frame_length [Default %d]\n", frame_length);
|
||||||
|
printf("\t-e ebno in dB [Default scan]\n");
|
||||||
|
printf("\t-t test: check errors on exit [Default disabled]\n");
|
||||||
|
printf("\t-s seed [Default 0=time]\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void parse_args(int argc, char **argv) {
|
||||||
|
int opt;
|
||||||
|
while ((opt = getopt(argc, argv, "inlstvekt")) != -1) {
|
||||||
|
switch (opt) {
|
||||||
|
case 'n':
|
||||||
|
nof_frames = atoi(argv[optind]);
|
||||||
|
break;
|
||||||
|
case 'k':
|
||||||
|
test_known_data = 1;
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
test_errors = 1;
|
||||||
|
break;
|
||||||
|
case 'i':
|
||||||
|
nof_iterations = atoi(argv[optind]);
|
||||||
|
break;
|
||||||
|
case 'l':
|
||||||
|
frame_length = atoi(argv[optind]);
|
||||||
|
break;
|
||||||
|
case 'e':
|
||||||
|
ebno_db = atof(argv[optind]);
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
seed = (unsigned int) strtoul(argv[optind], NULL, 0);
|
||||||
|
break;
|
||||||
|
case 'v':
|
||||||
|
verbose++;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
usage(argv[0]);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void output_matlab(float ber[MAX_ITERATIONS][SNR_POINTS], int snr_points) {
|
||||||
|
int i, j;
|
||||||
|
FILE *f = fopen("turbocoder_snr.m", "w");
|
||||||
|
if (!f) {
|
||||||
|
perror("fopen");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
fprintf(f, "ber=[");
|
||||||
|
for (j=0;j<MAX_ITERATIONS;j++) {
|
||||||
|
for (i = 0; i < snr_points; i++) {
|
||||||
|
fprintf(f, "%g ", ber[j][i]);
|
||||||
|
}
|
||||||
|
fprintf(f, ";\n");
|
||||||
|
}
|
||||||
|
fprintf(f, "];\n");
|
||||||
|
fprintf(f, "snr=linspace(%g,%g-%g/%d,%d);\n", SNR_MIN, SNR_MAX, SNR_MAX,
|
||||||
|
snr_points, snr_points);
|
||||||
|
fprintf(f, "semilogy(snr,ber,snr,0.5*erfc(sqrt(10.^(snr/10))));\n");
|
||||||
|
fprintf(f, "legend('1 iter','2 iter', '3 iter', '4 iter', 'theory-uncoded');");
|
||||||
|
fprintf(f, "grid on;\n");
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
int frame_cnt;
|
||||||
|
float *llr;
|
||||||
|
unsigned char *llr_c;
|
||||||
|
char *data_tx, *data_rx, *symbols;
|
||||||
|
int i, j;
|
||||||
|
float var[SNR_POINTS];
|
||||||
|
int snr_points;
|
||||||
|
float ber[MAX_ITERATIONS][SNR_POINTS];
|
||||||
|
unsigned int errors[100];
|
||||||
|
int coded_length;
|
||||||
|
struct timeval tdata[3];
|
||||||
|
float mean_usec;
|
||||||
|
tdec_t tdec;
|
||||||
|
tcod_t tcod;
|
||||||
|
|
||||||
|
parse_args(argc, argv);
|
||||||
|
|
||||||
|
if (!seed) {
|
||||||
|
seed = time(NULL);
|
||||||
|
}
|
||||||
|
srand(seed);
|
||||||
|
|
||||||
|
if (test_known_data) {
|
||||||
|
frame_length = KNOWN_DATA_LEN;
|
||||||
|
} else {
|
||||||
|
frame_length = lte_cb_size(lte_find_cb_index(frame_length));
|
||||||
|
}
|
||||||
|
|
||||||
|
coded_length = 3*(frame_length)+TOTALTAIL;
|
||||||
|
|
||||||
|
printf(" Frame length: %d\n", frame_length);
|
||||||
|
if (ebno_db < 100.0) {
|
||||||
|
printf(" EbNo: %.2f\n", ebno_db);
|
||||||
|
}
|
||||||
|
|
||||||
|
data_tx = malloc(frame_length * sizeof(char));
|
||||||
|
if (!data_tx) {
|
||||||
|
perror("malloc");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
data_rx = malloc(frame_length * sizeof(char));
|
||||||
|
if (!data_rx) {
|
||||||
|
perror("malloc");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
symbols = malloc(coded_length * sizeof(char));
|
||||||
|
if (!symbols) {
|
||||||
|
perror("malloc");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
llr = malloc(coded_length * sizeof(float));
|
||||||
|
if (!llr) {
|
||||||
|
perror("malloc");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
llr_c = malloc(coded_length * sizeof(char));
|
||||||
|
if (!llr_c) {
|
||||||
|
perror("malloc");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tcod_init(&tcod, frame_length)) {
|
||||||
|
fprintf(stderr, "Error initiating Turbo coder\n");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tdec_init(&tdec, frame_length)) {
|
||||||
|
fprintf(stderr, "Error initiating Turbo decoder\n");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
float ebno_inc, esno_db;
|
||||||
|
ebno_inc = (SNR_MAX - SNR_MIN) / SNR_POINTS;
|
||||||
|
if (ebno_db == 100.0) {
|
||||||
|
snr_points = SNR_POINTS;
|
||||||
|
for (i = 0; i < snr_points; i++) {
|
||||||
|
ebno_db = SNR_MIN + i * ebno_inc;
|
||||||
|
esno_db = ebno_db + 10 * log10((double) 1 / 3);
|
||||||
|
var[i] = sqrt(1 / (pow(10, esno_db / 10)));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
esno_db = ebno_db + 10 * log10((double) 1 / 3);
|
||||||
|
var[0] = sqrt(1 / (pow(10, esno_db / 10)));
|
||||||
|
snr_points = 1;
|
||||||
|
}
|
||||||
|
for (i = 0; i < snr_points; i++) {
|
||||||
|
mean_usec = 0;
|
||||||
|
frame_cnt = 0;
|
||||||
|
bzero(errors, sizeof(int) * MAX_ITERATIONS);
|
||||||
|
while (frame_cnt < nof_frames) {
|
||||||
|
|
||||||
|
/* generate data_tx */
|
||||||
|
for (j = 0; j < frame_length; j++) {
|
||||||
|
if (test_known_data) {
|
||||||
|
data_tx[j] = known_data[j];
|
||||||
|
} else {
|
||||||
|
data_tx[j] = rand() % 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* coded BER */
|
||||||
|
if (test_known_data) {
|
||||||
|
for (j=0;j<coded_length;j++) {
|
||||||
|
symbols[j] = known_data_encoded[j];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
tcod_encode(&tcod, data_tx, symbols);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (j = 0; j < coded_length; j++) {
|
||||||
|
llr[j] = symbols[j] ? sqrt(2) : -sqrt(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
ch_awgn_f(llr, llr, var[i], coded_length);
|
||||||
|
|
||||||
|
/* decoder */
|
||||||
|
tdec_reset(&tdec);
|
||||||
|
|
||||||
|
int t;
|
||||||
|
if (nof_iterations == -1) {
|
||||||
|
t = MAX_ITERATIONS;
|
||||||
|
} else {
|
||||||
|
t = nof_iterations;
|
||||||
|
}
|
||||||
|
for (j=0;j<t;j++) {
|
||||||
|
|
||||||
|
if (!j) gettimeofday(&tdata[1],NULL); // Only measure 1 iteration
|
||||||
|
tdec_iteration(&tdec, llr);
|
||||||
|
tdec_decision(&tdec, data_rx);
|
||||||
|
if (!j) gettimeofday(&tdata[2],NULL);
|
||||||
|
if (!j) get_time_interval(tdata);
|
||||||
|
if (!j) mean_usec = (float) mean_usec*0.9+(float) tdata[0].tv_usec*0.1;
|
||||||
|
|
||||||
|
/* check errors */
|
||||||
|
errors[j] += bit_diff(data_tx, data_rx, frame_length);
|
||||||
|
if (j < MAX_ITERATIONS) {
|
||||||
|
ber[j][i] = (float) errors[j] /(frame_cnt * frame_length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
frame_cnt++;
|
||||||
|
printf("Eb/No: %3.2f %10d/%d ",
|
||||||
|
SNR_MIN + i * ebno_inc,frame_cnt,nof_frames);
|
||||||
|
printf("BER: %.2e ",(float) errors[j-1] / (frame_cnt * frame_length));
|
||||||
|
printf("%3.1f Mbps (%6.2f usec)", (float) frame_length/mean_usec, mean_usec);
|
||||||
|
printf("\r");
|
||||||
|
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
if (snr_points == 1) {
|
||||||
|
if (test_known_data && seed == KNOWN_DATA_SEED
|
||||||
|
&& ebno_db == KNOWN_DATA_EBNO
|
||||||
|
&& frame_cnt == KNOWN_DATA_NFRAMES) {
|
||||||
|
for (j=0;j<MAX_ITERATIONS;j++) {
|
||||||
|
if (errors[j] > known_data_errors[j]) {
|
||||||
|
fprintf(stderr, "Expected %d errors but got %d\n",
|
||||||
|
known_data_errors[j], errors[j]);
|
||||||
|
exit(-1);
|
||||||
|
}else {
|
||||||
|
printf("Iter %d ok\n", j+1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (j=0;j<MAX_ITERATIONS;j++) {
|
||||||
|
printf("BER: %g\t%u errors\n",
|
||||||
|
(float) errors[j] / (frame_cnt * frame_length), errors[j]);
|
||||||
|
if (test_errors) {
|
||||||
|
if (errors[j] > get_expected_errors(frame_cnt, seed, j+1, frame_length, ebno_db)) {
|
||||||
|
fprintf(stderr, "Expected %d errors but got %d\n",
|
||||||
|
get_expected_errors(frame_cnt, seed, j+1, frame_length, ebno_db),
|
||||||
|
errors[j]);
|
||||||
|
exit(-1);
|
||||||
|
} else {
|
||||||
|
printf("Iter %d ok\n", j+1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(data_tx);
|
||||||
|
free(symbols);
|
||||||
|
free(llr);
|
||||||
|
free(llr_c);
|
||||||
|
free(data_rx);
|
||||||
|
|
||||||
|
tdec_free(&tdec);
|
||||||
|
tcod_free(&tcod);
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
output_matlab(ber, snr_points);
|
||||||
|
printf("Done\n");
|
||||||
|
exit(0);
|
||||||
|
}
|
@ -0,0 +1,168 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* \section COPYRIGHT
|
||||||
|
*
|
||||||
|
* Copyright 2013-2014 The libLTE Developers. See the
|
||||||
|
* COPYRIGHT file at the top-level directory of this distribution.
|
||||||
|
*
|
||||||
|
* \section LICENSE
|
||||||
|
*
|
||||||
|
* This file is part of the libLTE library.
|
||||||
|
*
|
||||||
|
* libLTE 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 3 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* libLTE 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.
|
||||||
|
*
|
||||||
|
* A copy of the GNU Lesser General Public License can be found in
|
||||||
|
* the LICENSE file in the top-level directory of this distribution
|
||||||
|
* and at http://www.gnu.org/licenses/.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int n;
|
||||||
|
unsigned int s;
|
||||||
|
int iterations;
|
||||||
|
int len;
|
||||||
|
float ebno;
|
||||||
|
int errors;
|
||||||
|
} expected_errors_t;
|
||||||
|
|
||||||
|
static expected_errors_t expected_errors[] = {
|
||||||
|
{ 100, 1, 1, 504, 1.0, 3989 },
|
||||||
|
{ 100, 1, 2, 504, 1.0, 1922 },
|
||||||
|
{ 100, 1, 3, 504, 1.0, 1096 },
|
||||||
|
{ 100, 1, 4, 504, 1.0, 957 },
|
||||||
|
|
||||||
|
{ 100, 1, 1, 504, 2.0, 803 },
|
||||||
|
{ 100, 1, 2, 504, 2.0, 47 },
|
||||||
|
{ 100, 1, 3, 504, 2.0, 7 },
|
||||||
|
{ 100, 1, 4, 504, 2.0, 0 },
|
||||||
|
|
||||||
|
{ 100, 1, 1, 6144, 1.5, 24719 },
|
||||||
|
{ 100, 1, 2, 6144, 1.5, 897 },
|
||||||
|
{ 100, 1, 3, 6144, 1.5, 2 },
|
||||||
|
{ 100, 1, 4, 6144, 1.5, 0 },
|
||||||
|
{ -1, 0, -1, -1, -1.0, -1}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
int get_expected_errors(int n, unsigned int s, int iterations, int len, float ebno) {
|
||||||
|
int i;
|
||||||
|
i = 0;
|
||||||
|
while (expected_errors[i].n != -1) {
|
||||||
|
if (expected_errors[i].n == n
|
||||||
|
&& expected_errors[i].s == s
|
||||||
|
&& expected_errors[i].len == len
|
||||||
|
&& expected_errors[i].iterations == iterations
|
||||||
|
&& expected_errors[i].ebno == ebno) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return expected_errors[i].errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define KNOWN_DATA_NFRAMES 1
|
||||||
|
#define KNOWN_DATA_SEED 1
|
||||||
|
#define KNOWN_DATA_EBNO 0.5
|
||||||
|
const int known_data_errors[4] = {47, 18, 0, 0};
|
||||||
|
|
||||||
|
#define KNOWN_DATA_LEN 504
|
||||||
|
const char known_data[KNOWN_DATA_LEN] = { 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1,
|
||||||
|
0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1,
|
||||||
|
0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1,
|
||||||
|
1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0,
|
||||||
|
0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1,
|
||||||
|
1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0,
|
||||||
|
1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0,
|
||||||
|
1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0,
|
||||||
|
1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1,
|
||||||
|
0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0,
|
||||||
|
0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0,
|
||||||
|
1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1,
|
||||||
|
1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0,
|
||||||
|
0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1,
|
||||||
|
1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0,
|
||||||
|
0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0,
|
||||||
|
1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1,
|
||||||
|
1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1,
|
||||||
|
1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1 };
|
||||||
|
|
||||||
|
const char known_data_encoded[3 * KNOWN_DATA_LEN + 12] = { 0, 0, 0, 0, 0, 1, 1,
|
||||||
|
1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1,
|
||||||
|
1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0,
|
||||||
|
0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0,
|
||||||
|
0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1,
|
||||||
|
0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1,
|
||||||
|
1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1,
|
||||||
|
0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1,
|
||||||
|
1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0,
|
||||||
|
1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1,
|
||||||
|
0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0,
|
||||||
|
1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1,
|
||||||
|
0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1,
|
||||||
|
0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0,
|
||||||
|
0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0,
|
||||||
|
0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0,
|
||||||
|
0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1,
|
||||||
|
0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0,
|
||||||
|
0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1,
|
||||||
|
0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0,
|
||||||
|
1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0,
|
||||||
|
1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0,
|
||||||
|
1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1,
|
||||||
|
1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1,
|
||||||
|
1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0,
|
||||||
|
0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1,
|
||||||
|
1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1,
|
||||||
|
0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1,
|
||||||
|
1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1,
|
||||||
|
1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0,
|
||||||
|
0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0,
|
||||||
|
1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0,
|
||||||
|
0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1,
|
||||||
|
1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0,
|
||||||
|
0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1,
|
||||||
|
0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0,
|
||||||
|
0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1,
|
||||||
|
0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0,
|
||||||
|
0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1,
|
||||||
|
1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0,
|
||||||
|
0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1,
|
||||||
|
1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1,
|
||||||
|
1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1,
|
||||||
|
0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1,
|
||||||
|
0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0,
|
||||||
|
1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0,
|
||||||
|
1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1,
|
||||||
|
1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1,
|
||||||
|
1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0,
|
||||||
|
0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0,
|
||||||
|
1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1,
|
||||||
|
1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0,
|
||||||
|
0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0,
|
||||||
|
0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0,
|
||||||
|
1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0,
|
||||||
|
1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0,
|
||||||
|
1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1,
|
||||||
|
1, 0, 1, 1, 1 };
|
@ -0,0 +1,518 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* \section COPYRIGHT
|
||||||
|
*
|
||||||
|
* Copyright 2013-2014 The libLTE Developers. See the
|
||||||
|
* COPYRIGHT file at the top-level directory of this distribution.
|
||||||
|
*
|
||||||
|
* \section LICENSE
|
||||||
|
*
|
||||||
|
* This file is part of the libLTE library.
|
||||||
|
*
|
||||||
|
* libLTE 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 3 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* libLTE 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.
|
||||||
|
*
|
||||||
|
* A copy of the GNU Lesser General Public License can be found in
|
||||||
|
* the LICENSE file in the top-level directory of this distribution
|
||||||
|
* and at http://www.gnu.org/licenses/.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <strings.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include "lte/common/base.h"
|
||||||
|
#include "lte/utils/bit.h"
|
||||||
|
#include "lte/utils/vector.h"
|
||||||
|
#include "lte/utils/debug.h"
|
||||||
|
#include "lte/phch/ra.h"
|
||||||
|
#include "lte/utils/bit.h"
|
||||||
|
|
||||||
|
#include "tbs_tables.h"
|
||||||
|
|
||||||
|
#define min(a,b) (a<b?a:b)
|
||||||
|
|
||||||
|
|
||||||
|
void ra_prb_fprint(FILE *f, ra_prb_slot_t *prb) {
|
||||||
|
int i, j, nrows;
|
||||||
|
nrows = (prb->nof_prb - 1)/ 25 + 1;
|
||||||
|
for (j=0;j<nrows;j++) {
|
||||||
|
for (i=0;i<min(25, prb->nof_prb-j*25);i++) {
|
||||||
|
fprintf(f, "%3d, ", prb->prb_idx[j*25+i]);
|
||||||
|
}
|
||||||
|
fprintf(f, "\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Compute PRB allocation for Downlink as defined in 8.1 of 36.213 */
|
||||||
|
int ra_prb_get_ul(ra_prb_slot_t *prb, ra_pusch_t *ra, int nof_prb) {
|
||||||
|
int i;
|
||||||
|
if (ra->type2_alloc.mode != t2_loc) {
|
||||||
|
fprintf(stderr, "Uplink only accepts type2 localized scheduling\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
for (i=0;i<ra->type2_alloc.L_crb;i++) {
|
||||||
|
prb->prb_idx[i] = i+ra->type2_alloc.RB_start;
|
||||||
|
prb->nof_prb++;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Compute PRB allocation for Downlink as defined in 7.1.6 of 36.213 */
|
||||||
|
int ra_prb_get_dl(ra_prb_t *prb_dist, ra_pdsch_t *ra, int nof_prb) {
|
||||||
|
int i, j;
|
||||||
|
uint32_t bitmask;
|
||||||
|
int P = ra_type0_P(nof_prb);
|
||||||
|
ra_prb_slot_t *prb;
|
||||||
|
|
||||||
|
bzero(prb_dist, sizeof(ra_prb_t));
|
||||||
|
switch(ra->alloc_type) {
|
||||||
|
case alloc_type0:
|
||||||
|
prb = &prb_dist->slot1;
|
||||||
|
prb_dist->is_dist = false;
|
||||||
|
bitmask = ra->type0_alloc.rbg_bitmask;
|
||||||
|
int nb = (int) ceilf((float)nof_prb/P);
|
||||||
|
for (i=0;i<nb;i++) {
|
||||||
|
if (bitmask & (1<<(nb-i-1))) {
|
||||||
|
for (j=0;j<P;j++) {
|
||||||
|
prb->prb_idx[prb->nof_prb] = i*P+j;
|
||||||
|
prb->nof_prb++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case alloc_type1:
|
||||||
|
prb = &prb_dist->slot1;
|
||||||
|
prb_dist->is_dist = false;
|
||||||
|
int n_rb_type1 = ra_type1_N_rb(nof_prb);
|
||||||
|
int n_rb_rbg_subset;
|
||||||
|
if (ra->type1_alloc.rbg_subset < (nof_prb/P) % P) {
|
||||||
|
n_rb_rbg_subset = ((nof_prb-1)/(P*P)) * P + P;
|
||||||
|
} else if (ra->type1_alloc.rbg_subset == ((nof_prb/P) % P)) {
|
||||||
|
n_rb_rbg_subset = ((nof_prb-1)/(P*P)) * P + ((nof_prb-1)%P)+1;
|
||||||
|
} else {
|
||||||
|
n_rb_rbg_subset = ((nof_prb-1)/(P*P)) * P;
|
||||||
|
}
|
||||||
|
int shift = ra->type1_alloc.shift?(n_rb_rbg_subset-n_rb_type1):0;
|
||||||
|
bitmask = ra->type1_alloc.vrb_bitmask;
|
||||||
|
for (i=0;i<n_rb_type1;i++) {
|
||||||
|
if (bitmask & (1<<(n_rb_type1-i-1))) {
|
||||||
|
prb->prb_idx[prb->nof_prb] = ((i+shift)/P)*P*P+
|
||||||
|
ra->type1_alloc.rbg_subset*P+(i+shift)%P;
|
||||||
|
prb->nof_prb++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case alloc_type2:
|
||||||
|
if (ra->type2_alloc.mode == t2_loc) {
|
||||||
|
prb = &prb_dist->slot1;
|
||||||
|
prb_dist->is_dist = false;
|
||||||
|
for (i=0;i<ra->type2_alloc.L_crb;i++) {
|
||||||
|
prb->prb_idx[i] = i+ra->type2_alloc.RB_start;
|
||||||
|
prb->nof_prb++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Mapping of Virtual to Physical RB for distributed type is defined in
|
||||||
|
* 6.2.3.2 of 36.211
|
||||||
|
*/
|
||||||
|
prb_dist->is_dist = true;
|
||||||
|
int N_gap, N_tilde_vrb, n_tilde_vrb, n_tilde_prb, n_tilde2_prb, N_null, N_row, n_vrb;
|
||||||
|
int n_tilde_prb_odd, n_tilde_prb_even;
|
||||||
|
if (ra->type2_alloc.n_gap == t2_ng1) {
|
||||||
|
N_tilde_vrb = nof_prb;
|
||||||
|
N_gap = ra_type2_ngap(nof_prb, true);
|
||||||
|
} else {
|
||||||
|
N_tilde_vrb = 2*nof_prb;
|
||||||
|
N_gap = ra_type2_ngap(nof_prb, false);
|
||||||
|
}
|
||||||
|
N_row = (int) ceilf((float) N_tilde_vrb/(4*P))*P;
|
||||||
|
N_null = 4*N_row-N_tilde_vrb;
|
||||||
|
for (i=0;i<ra->type2_alloc.L_crb;i++) {
|
||||||
|
n_vrb = i+ra->type2_alloc.RB_start;
|
||||||
|
n_tilde_vrb = n_vrb%N_tilde_vrb;
|
||||||
|
n_tilde_prb = 2*N_row*(n_tilde_vrb % 2)+n_tilde_vrb/2+N_tilde_vrb*(n_vrb/N_tilde_vrb);
|
||||||
|
n_tilde2_prb = N_row*(n_tilde_vrb % 4)+n_tilde_vrb/4+N_tilde_vrb*(n_vrb/N_tilde_vrb);
|
||||||
|
|
||||||
|
if (N_null != 0 && n_tilde_vrb >= (N_tilde_vrb - N_null) && (n_tilde_vrb%2) == 1) {
|
||||||
|
n_tilde_prb_odd = n_tilde_prb-N_row;
|
||||||
|
} else if (N_null != 0 && n_tilde_vrb >= (N_tilde_vrb - N_null) && (n_tilde_vrb%2) == 0) {
|
||||||
|
n_tilde_prb_odd = n_tilde_prb-N_row+N_null/2;
|
||||||
|
} else if (N_null != 0 && n_tilde_vrb < (N_tilde_vrb - N_null) && (n_tilde_vrb%4) >= 2) {
|
||||||
|
n_tilde_prb_odd = n_tilde2_prb-N_null/2;
|
||||||
|
} else {
|
||||||
|
n_tilde_prb_odd = n_tilde2_prb;
|
||||||
|
}
|
||||||
|
n_tilde_prb_even = (n_tilde_prb_odd+N_tilde_vrb/2)%N_tilde_vrb+N_tilde_vrb*(n_vrb/N_tilde_vrb);
|
||||||
|
|
||||||
|
if (n_tilde_prb_odd < N_tilde_vrb/2) {
|
||||||
|
prb_dist->slot1.prb_idx[i] = n_tilde_prb_odd;
|
||||||
|
} else {
|
||||||
|
prb_dist->slot1.prb_idx[i] = n_tilde_prb_odd+N_gap-N_tilde_vrb/2;
|
||||||
|
}
|
||||||
|
prb_dist->slot1.nof_prb++;
|
||||||
|
if (n_tilde_prb_even < N_tilde_vrb/2) {
|
||||||
|
prb_dist->slot2.prb_idx[i] = n_tilde_prb_even;
|
||||||
|
} else {
|
||||||
|
prb_dist->slot2.prb_idx[i] = n_tilde_prb_even+N_gap-N_tilde_vrb/2;
|
||||||
|
}
|
||||||
|
prb_dist->slot2.nof_prb++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Returns the number of allocated PRB for Uplink */
|
||||||
|
int ra_nprb_ul(ra_pusch_t *ra, int nof_prb) {
|
||||||
|
return ra->type2_alloc.L_crb;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Returns the number of allocated PRB for Downlink */
|
||||||
|
int ra_nprb_dl(ra_pdsch_t *ra, int nof_prb) {
|
||||||
|
int nprb;
|
||||||
|
int nof_rbg, P;
|
||||||
|
switch(ra->alloc_type) {
|
||||||
|
case alloc_type0:
|
||||||
|
// Get the number of allocated RBG except the last RBG
|
||||||
|
nof_rbg = bit_count(ra->type0_alloc.rbg_bitmask & 0xFFFFFFFE);
|
||||||
|
P = ra_type0_P(nof_prb);
|
||||||
|
if (nof_rbg > (int) ceilf((float)nof_prb/P)) {
|
||||||
|
fprintf(stderr, "Number of RGB (%d) can not exceed %d\n", nof_prb,
|
||||||
|
(int) ceilf((float)nof_prb/P));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
nprb = nof_rbg * P;
|
||||||
|
|
||||||
|
// last RBG may have smaller size. Add if set
|
||||||
|
int P_last = (nof_prb%P);
|
||||||
|
if (!P_last) P_last = P;
|
||||||
|
nprb += P_last*(ra->type0_alloc.rbg_bitmask&1);
|
||||||
|
break;
|
||||||
|
case alloc_type1:
|
||||||
|
nprb = bit_count(ra->type1_alloc.vrb_bitmask);
|
||||||
|
if (nprb > ra_type1_N_rb(nof_prb)) {
|
||||||
|
fprintf(stderr, "Number of RB (%d) can not exceed %d\n", nprb,
|
||||||
|
ra_type1_N_rb(nof_prb));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case alloc_type2:
|
||||||
|
nprb = ra->type2_alloc.L_crb;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return nprb;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* RBG size for type0 scheduling as in table 7.1.6.1-1 of 36.213 */
|
||||||
|
int ra_type0_P(int nof_prb) {
|
||||||
|
if (nof_prb <= 10) {
|
||||||
|
return 1;
|
||||||
|
} else if (nof_prb <= 26) {
|
||||||
|
return 2;
|
||||||
|
} else if (nof_prb <= 63) {
|
||||||
|
return 3;
|
||||||
|
} else {
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Returns N_rb_type1 according to section 7.1.6.2 */
|
||||||
|
int ra_type1_N_rb(int nof_prb) {
|
||||||
|
int P = ra_type0_P(nof_prb);
|
||||||
|
return (int) ceilf((float) nof_prb/P) - (int) ceilf(log2f((float) P)) - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Convert Type2 scheduling L_crb and RB_start to RIV value */
|
||||||
|
uint32_t ra_type2_to_riv(uint16_t L_crb, uint16_t RB_start, int nof_prb) {
|
||||||
|
uint32_t riv;
|
||||||
|
if (L_crb <= (int) nof_prb/2) {
|
||||||
|
riv = nof_prb*(L_crb-1) + RB_start;
|
||||||
|
} else {
|
||||||
|
riv = nof_prb*(nof_prb-L_crb+1) + nof_prb - 1 - RB_start;
|
||||||
|
}
|
||||||
|
return riv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Convert Type2 scheduling RIV value to L_crb and RB_start values */
|
||||||
|
void ra_type2_from_riv(uint32_t riv, uint16_t *L_crb, uint16_t *RB_start, int nof_prb, int nof_vrb) {
|
||||||
|
*L_crb = (int) (riv/nof_prb) + 1;
|
||||||
|
*RB_start = riv%nof_prb;
|
||||||
|
if (*L_crb > nof_vrb - *RB_start) {
|
||||||
|
*L_crb = nof_prb - (int) (riv/nof_prb) + 1;
|
||||||
|
*RB_start = nof_prb - riv%nof_prb - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Table 6.2.3.2-1 in 36.211 */
|
||||||
|
int ra_type2_ngap(int nof_prb, bool ngap_is_1) {
|
||||||
|
if (nof_prb <= 10) {
|
||||||
|
return nof_prb/2;
|
||||||
|
} else if (nof_prb == 11) {
|
||||||
|
return 4;
|
||||||
|
} else if (nof_prb <= 19) {
|
||||||
|
return 8;
|
||||||
|
} else if (nof_prb <= 26) {
|
||||||
|
return 12;
|
||||||
|
} else if (nof_prb <= 44) {
|
||||||
|
return 18;
|
||||||
|
} else if (nof_prb <= 49) {
|
||||||
|
return 27;
|
||||||
|
} else if (nof_prb <= 63) {
|
||||||
|
return ngap_is_1?27:9;
|
||||||
|
} else if (nof_prb <= 79) {
|
||||||
|
return ngap_is_1?32:16;
|
||||||
|
} else {
|
||||||
|
return ngap_is_1?48:16;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Table 7.1.6.3-1 in 36.213 */
|
||||||
|
int ra_type2_n_rb_step(int nof_prb) {
|
||||||
|
if (nof_prb < 50) {
|
||||||
|
return 2;
|
||||||
|
} else {
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* as defined in 6.2.3.2 of 36.211 */
|
||||||
|
int ra_type2_n_vrb_dl(int nof_prb, bool ngap_is_1) {
|
||||||
|
int ngap = ra_type2_ngap(nof_prb, ngap_is_1);
|
||||||
|
if (ngap_is_1) {
|
||||||
|
return 2*(ngap<(nof_prb-ngap)?ngap:nof_prb-ngap);
|
||||||
|
} else {
|
||||||
|
return ((int) nof_prb/ngap)*2*ngap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Converts ra_mcs_t structure to MCS index for both Uplink and Downlink */
|
||||||
|
uint8_t ra_mcs_to_table_idx(ra_mcs_t *mcs) {
|
||||||
|
switch (mcs->mod) {
|
||||||
|
case QPSK:
|
||||||
|
return mcs->tbs_idx;
|
||||||
|
case QAM16:
|
||||||
|
return mcs->tbs_idx + 1;
|
||||||
|
case QAM64:
|
||||||
|
return mcs->tbs_idx + 2;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Converts MCS index to ra_mcs_t structure for Downlink as defined inTable 7.1.7.1-1 on 36.213 */
|
||||||
|
int ra_mcs_from_idx_dl(uint8_t idx, ra_mcs_t *mcs) {
|
||||||
|
if (idx < 10) {
|
||||||
|
mcs->mod = QPSK;
|
||||||
|
mcs->tbs_idx = idx;
|
||||||
|
} else if (idx < 17) {
|
||||||
|
mcs->mod = QAM16;
|
||||||
|
mcs->tbs_idx = idx-1;
|
||||||
|
} else if (idx < 29) {
|
||||||
|
mcs->mod = QAM64;
|
||||||
|
mcs->tbs_idx = idx-2;
|
||||||
|
} else if (idx == 29) {
|
||||||
|
mcs->mod = QPSK;
|
||||||
|
mcs->tbs_idx = 0;
|
||||||
|
} else if (idx == 30) {
|
||||||
|
mcs->mod = QAM16;
|
||||||
|
mcs->tbs_idx = 0;
|
||||||
|
} else if (idx == 31) {
|
||||||
|
mcs->mod = QAM64;
|
||||||
|
mcs->tbs_idx = 0;
|
||||||
|
} else {
|
||||||
|
mcs->mod = MOD_NULL;
|
||||||
|
mcs->tbs_idx = 0;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Converts MCS index to ra_mcs_t structure for Uplink as defined in Table 8.6.1-1 on 36.213 */
|
||||||
|
int ra_mcs_from_idx_ul(uint8_t idx, ra_mcs_t *mcs) {
|
||||||
|
if (idx < 11) {
|
||||||
|
mcs->mod = QPSK;
|
||||||
|
mcs->tbs_idx = idx;
|
||||||
|
} else if (idx < 21) {
|
||||||
|
mcs->mod = QAM16;
|
||||||
|
mcs->tbs_idx = idx-1;
|
||||||
|
} else if (idx < 29) {
|
||||||
|
mcs->mod = QAM64;
|
||||||
|
mcs->tbs_idx = idx-2;
|
||||||
|
} else {
|
||||||
|
mcs->mod = MOD_NULL;
|
||||||
|
mcs->tbs_idx = 0;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Downlink Transport Block size for Format 1C as defined in 7.1.7.2.2-1 on 36.213 */
|
||||||
|
int ra_tbs_from_idx_format1c(uint8_t tbs_idx) {
|
||||||
|
if (tbs_idx < 32) {
|
||||||
|
return tbs_format1c_table[tbs_idx];
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Returns lowest nearest index of TBS value in table 7.1.7.2.2-1 on 36.213
|
||||||
|
* or -1 if the TBS value is not within the valid TBS values
|
||||||
|
*/
|
||||||
|
int ra_tbs_to_table_idx_format1c(int tbs) {
|
||||||
|
int idx;
|
||||||
|
if (tbs < tbs_format1c_table[0]) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
for (idx=1;idx<32;idx++) {
|
||||||
|
if (tbs_format1c_table[idx-1] <= tbs &&
|
||||||
|
tbs_format1c_table[idx] >= tbs) {
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Downlink Transport Block size determination as defined in 7.1.7.2 on 36.213 */
|
||||||
|
int ra_tbs_from_idx(uint8_t tbs_idx, int n_prb ) {
|
||||||
|
if (tbs_idx < 27 && n_prb > 0 && n_prb <= 110) {
|
||||||
|
return tbs_table[tbs_idx][n_prb-1];
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Returns lowest nearest index of TBS value in table 7.1.7.2 on 36.213
|
||||||
|
* or -1 if the TBS value is not within the valid TBS values
|
||||||
|
*/
|
||||||
|
int ra_tbs_to_table_idx(int tbs, int n_prb) {
|
||||||
|
int idx;
|
||||||
|
if (n_prb > 0 && n_prb <= 110) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (tbs < tbs_table[0][n_prb]) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
for (idx=1;idx<28;idx++) {
|
||||||
|
if (tbs_table[idx-1][n_prb] <= tbs &&
|
||||||
|
tbs_table[idx][n_prb] >= tbs) {
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *ra_mod_string(ra_mod_t mod) {
|
||||||
|
switch (mod) {
|
||||||
|
case QPSK:
|
||||||
|
return "QPSK";
|
||||||
|
case QAM16:
|
||||||
|
return "QAM16";
|
||||||
|
case QAM64:
|
||||||
|
return "QAM64";
|
||||||
|
default:
|
||||||
|
return "N/A";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ra_pusch_fprint(FILE *f, ra_pusch_t *ra, int nof_prb) {
|
||||||
|
fprintf(f, "Frequency Hopping:\t");
|
||||||
|
if (ra->freq_hop_fl == hop_disabled) {
|
||||||
|
fprintf(f, "No");
|
||||||
|
} else {
|
||||||
|
fprintf(f, "Yes");
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char *ra_type_string(ra_type_t alloc_type) {
|
||||||
|
switch(alloc_type) {
|
||||||
|
case alloc_type0:
|
||||||
|
return "Type 0";
|
||||||
|
case alloc_type1:
|
||||||
|
return "Type 1";
|
||||||
|
case alloc_type2:
|
||||||
|
return "Type 2";
|
||||||
|
default:
|
||||||
|
return "N/A";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ra_pdsch_set_mcs_index(ra_pdsch_t *ra, uint8_t mcs_idx) {
|
||||||
|
ra->mcs.mod = MOD_NULL;
|
||||||
|
ra->mcs.mcs_idx = mcs_idx;
|
||||||
|
}
|
||||||
|
void ra_pdsch_set_mcs(ra_pdsch_t *ra, ra_mod_t mod, uint8_t tbs_idx) {
|
||||||
|
ra->mcs.mod = mod;
|
||||||
|
ra->mcs.tbs_idx = tbs_idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ra_pdsch_fprint(FILE *f, ra_pdsch_t *ra, int nof_prb) {
|
||||||
|
fprintf(f, " - Resource Allocation Type:\t\t%s\n",ra_type_string(ra->alloc_type));
|
||||||
|
switch(ra->alloc_type) {
|
||||||
|
case alloc_type0:
|
||||||
|
fprintf(f, " + Resource Block Group Size:\t\t%d\n",ra_type0_P(nof_prb));
|
||||||
|
fprintf(f, " + RBG Bitmap:\t\t\t0x%x\n",ra->type0_alloc.rbg_bitmask);
|
||||||
|
break;
|
||||||
|
case alloc_type1:
|
||||||
|
fprintf(f, " + Resource Block Group Size:\t\t%d\n",ra_type0_P(nof_prb));
|
||||||
|
fprintf(f, " + RBG Bitmap:\t\t\t0x%x\n",ra->type1_alloc.vrb_bitmask);
|
||||||
|
fprintf(f, " + RBG Subset:\t\t\t%d\n",ra->type1_alloc.rbg_subset);
|
||||||
|
fprintf(f, " + RBG Shift:\t\t\t\t%s\n",ra->type1_alloc.shift?"Yes":"No");
|
||||||
|
break;
|
||||||
|
case alloc_type2:
|
||||||
|
fprintf(f, " + Type:\t\t\t\t%s\n",
|
||||||
|
ra->type2_alloc.mode==t2_loc?"Localized":"Distributed");
|
||||||
|
fprintf(f, " + Resource Indicator Value:\t\t%d\n",ra->type2_alloc.riv);
|
||||||
|
if (ra->type2_alloc.mode == t2_loc) {
|
||||||
|
fprintf(f, " + VRB Assignment:\t\t\t%d VRB starting with VRB %d\n",
|
||||||
|
ra->type2_alloc.L_crb, ra->type2_alloc.RB_start);
|
||||||
|
} else {
|
||||||
|
fprintf(f, " + VRB Assignment:\t\t\t%d VRB starting with VRB %d\n",
|
||||||
|
ra->type2_alloc.L_crb, ra->type2_alloc.RB_start);
|
||||||
|
fprintf(f, " + VRB gap selection:\t\t\tGap %d\n",
|
||||||
|
ra->type2_alloc.n_gap == t2_ng1?1:2);
|
||||||
|
fprintf(f, " + VRB gap:\t\t\t\t%d\n",
|
||||||
|
ra_type2_ngap(nof_prb, ra->type2_alloc.n_gap == t2_ng1));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ra_prb_t alloc;
|
||||||
|
ra_prb_get_dl(&alloc, ra, nof_prb);
|
||||||
|
if (alloc.is_dist) {
|
||||||
|
fprintf(f, " - PRB Bitmap Assignment 1st slot:\n");
|
||||||
|
ra_prb_fprint(f, &alloc.slot1);
|
||||||
|
fprintf(f, " - PRB Bitmap Assignment 2nd slot:\n");
|
||||||
|
ra_prb_fprint(f, &alloc.slot2);
|
||||||
|
} else {
|
||||||
|
fprintf(f, " - PRB Bitmap Assignment:\n");
|
||||||
|
ra_prb_fprint(f, &alloc.slot1);
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(f, " - Number of PRBs:\t\t\t%d\n", ra_nprb_dl(ra, nof_prb));
|
||||||
|
fprintf(f, " - Modulation and coding scheme index:\t%d\n", ra->mcs.mcs_idx);
|
||||||
|
fprintf(f, " - Modulation type:\t\t\t%s\n", ra_mod_string(ra->mcs.mod));
|
||||||
|
fprintf(f, " - Transport block size:\t\t%d\n", ra->mcs.tbs);
|
||||||
|
fprintf(f, " - HARQ process:\t\t\t%d\n", ra->harq_process);
|
||||||
|
fprintf(f, " - New data indicator:\t\t\t%s\n", ra->ndi?"Yes":"No");
|
||||||
|
fprintf(f, " - Redundancy version:\t\t\t%d\n", ra->rv_idx);
|
||||||
|
fprintf(f, " - TPC command for PUCCH:\t\t--\n");
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,278 @@
|
|||||||
|
|
||||||
|
const int tbs_format1c_table[32] = {
|
||||||
|
40, 56, 72, 120, 136, 144, 176, 208, 224, 256, 280, 296, 328, 336, 392, 488,
|
||||||
|
552, 600, 632, 696, 776, 840, 904, 1000, 1064, 1128, 1224, 1288, 1384, 1480, 1608, 1736
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* Transport Block Size from 3GPP TS 36.213 v10.3.0 table 7.1.7.2.1-1 */
|
||||||
|
const int tbs_table[27][110] = {{ 16, 32, 56, 88, 120, 152, 176, 208, 224, 256, 288,
|
||||||
|
328, 344, 376, 392, 424, 456, 488, 504, 536, 568, 600,
|
||||||
|
616, 648, 680, 712, 744, 776, 776, 808, 840, 872, 904,
|
||||||
|
936, 968, 1000, 1032, 1032, 1064, 1096, 1128, 1160, 1192, 1224,
|
||||||
|
1256, 1256, 1288, 1320, 1352, 1384, 1416, 1416, 1480, 1480, 1544,
|
||||||
|
1544, 1608, 1608, 1608, 1672, 1672, 1736, 1736, 1800, 1800, 1800,
|
||||||
|
1864, 1864, 1928, 1928, 1992, 1992, 2024, 2088, 2088, 2088, 2152,
|
||||||
|
2152, 2216, 2216, 2280, 2280, 2280, 2344, 2344, 2408, 2408, 2472,
|
||||||
|
2472, 2536, 2536, 2536, 2600, 2600, 2664, 2664, 2728, 2728, 2728,
|
||||||
|
2792, 2792, 2856, 2856, 2856, 2984, 2984, 2984, 2984, 2984, 3112},
|
||||||
|
{ 24, 56, 88, 144, 176, 208, 224, 256, 328, 344, 376,
|
||||||
|
424, 456, 488, 520, 568, 600, 632, 680, 712, 744, 776,
|
||||||
|
808, 872, 904, 936, 968, 1000, 1032, 1064, 1128, 1160, 1192,
|
||||||
|
1224, 1256, 1288, 1352, 1384, 1416, 1416, 1480, 1544, 1544, 1608,
|
||||||
|
1608, 1672, 1736, 1736, 1800, 1800, 1864, 1864, 1928, 1992, 1992,
|
||||||
|
2024, 2088, 2088, 2152, 2152, 2216, 2280, 2280, 2344, 2344, 2408,
|
||||||
|
2472, 2472, 2536, 2536, 2600, 2600, 2664, 2728, 2728, 2792, 2792,
|
||||||
|
2856, 2856, 2856, 2984, 2984, 2984, 3112, 3112, 3112, 3240, 3240,
|
||||||
|
3240, 3240, 3368, 3368, 3368, 3496, 3496, 3496, 3496, 3624, 3624,
|
||||||
|
3624, 3752, 3752, 3752, 3752, 3880, 3880, 3880, 4008, 4008, 4008},
|
||||||
|
{ 32, 72, 144, 176, 208, 256, 296, 328, 376, 424, 472,
|
||||||
|
520, 568, 616, 648, 696, 744, 776, 840, 872, 936, 968,
|
||||||
|
1000, 1064, 1096, 1160, 1192, 1256, 1288, 1320, 1384, 1416, 1480,
|
||||||
|
1544, 1544, 1608, 1672, 1672, 1736, 1800, 1800, 1864, 1928, 1992,
|
||||||
|
2024, 2088, 2088, 2152, 2216, 2216, 2280, 2344, 2344, 2408, 2472,
|
||||||
|
2536, 2536, 2600, 2664, 2664, 2728, 2792, 2856, 2856, 2856, 2984,
|
||||||
|
2984, 3112, 3112, 3112, 3240, 3240, 3240, 3368, 3368, 3368, 3496,
|
||||||
|
3496, 3496, 3624, 3624, 3624, 3752, 3752, 3880, 3880, 3880, 4008,
|
||||||
|
4008, 4008, 4136, 4136, 4136, 4264, 4264, 4264, 4392, 4392, 4392,
|
||||||
|
4584, 4584, 4584, 4584, 4584, 4776, 4776, 4776, 4776, 4968, 4968},
|
||||||
|
{ 40, 104, 176, 208, 256, 328, 392, 440, 504, 568, 616,
|
||||||
|
680, 744, 808, 872, 904, 968, 1032, 1096, 1160, 1224, 1256,
|
||||||
|
1320, 1384, 1416, 1480, 1544, 1608, 1672, 1736, 1800, 1864, 1928,
|
||||||
|
1992, 2024, 2088, 2152, 2216, 2280, 2344, 2408, 2472, 2536, 2536,
|
||||||
|
2600, 2664, 2728, 2792, 2856, 2856, 2984, 2984, 3112, 3112, 3240,
|
||||||
|
3240, 3368, 3368, 3496, 3496, 3624, 3624, 3624, 3752, 3752, 3880,
|
||||||
|
3880, 4008, 4008, 4136, 4136, 4264, 4264, 4392, 4392, 4392, 4584,
|
||||||
|
4584, 4584, 4776, 4776, 4776, 4776, 4968, 4968, 4968, 5160, 5160,
|
||||||
|
5160, 5352, 5352, 5352, 5352, 5544, 5544, 5544, 5736, 5736, 5736,
|
||||||
|
5736, 5992, 5992, 5992, 5992, 6200, 6200, 6200, 6200, 6456, 6456},
|
||||||
|
{ 56, 120, 208, 256, 328, 408, 488, 552, 632, 696, 776,
|
||||||
|
840, 904, 1000, 1064, 1128, 1192, 1288, 1352, 1416, 1480, 1544,
|
||||||
|
1608, 1736, 1800, 1864, 1928, 1992, 2088, 2152, 2216, 2280, 2344,
|
||||||
|
2408, 2472, 2600, 2664, 2728, 2792, 2856, 2984, 2984, 3112, 3112,
|
||||||
|
3240, 3240, 3368, 3496, 3496, 3624, 3624, 3752, 3752, 3880, 4008,
|
||||||
|
4008, 4136, 4136, 4264, 4264, 4392, 4392, 4584, 4584, 4584, 4776,
|
||||||
|
4776, 4968, 4968, 4968, 5160, 5160, 5160, 5352, 5352, 5544, 5544,
|
||||||
|
5544, 5736, 5736, 5736, 5992, 5992, 5992, 5992, 6200, 6200, 6200,
|
||||||
|
6456, 6456, 6456, 6456, 6712, 6712, 6712, 6968, 6968, 6968, 6968,
|
||||||
|
7224, 7224, 7224, 7480, 7480, 7480, 7480, 7736, 7736, 7736, 7992},
|
||||||
|
{ 72, 144, 224, 328, 424, 504, 600, 680, 776, 872, 968,
|
||||||
|
1032, 1128, 1224, 1320, 1384, 1480, 1544, 1672, 1736, 1864, 1928,
|
||||||
|
2024, 2088, 2216, 2280, 2344, 2472, 2536, 2664, 2728, 2792, 2856,
|
||||||
|
2984, 3112, 3112, 3240, 3368, 3496, 3496, 3624, 3752, 3752, 3880,
|
||||||
|
4008, 4008, 4136, 4264, 4392, 4392, 4584, 4584, 4776, 4776, 4776,
|
||||||
|
4968, 4968, 5160, 5160, 5352, 5352, 5544, 5544, 5736, 5736, 5736,
|
||||||
|
5992, 5992, 5992, 6200, 6200, 6200, 6456, 6456, 6712, 6712, 6712,
|
||||||
|
6968, 6968, 6968, 7224, 7224, 7224, 7480, 7480, 7480, 7736, 7736,
|
||||||
|
7736, 7992, 7992, 7992, 8248, 8248, 8248, 8504, 8504, 8760, 8760,
|
||||||
|
8760, 8760, 9144, 9144, 9144, 9144, 9528, 9528, 9528, 9528, 9528},
|
||||||
|
{ 328, 176, 256, 392, 504, 600, 712, 808, 936, 1032, 1128,
|
||||||
|
1224, 1352, 1480, 1544, 1672, 1736, 1864, 1992, 2088, 2216, 2280,
|
||||||
|
2408, 2472, 2600, 2728, 2792, 2984, 2984, 3112, 3240, 3368, 3496,
|
||||||
|
3496, 3624, 3752, 3880, 4008, 4136, 4136, 4264, 4392, 4584, 4584,
|
||||||
|
4776, 4776, 4968, 4968, 5160, 5160, 5352, 5352, 5544, 5736, 5736,
|
||||||
|
5992, 5992, 5992, 6200, 6200, 6456, 6456, 6456, 6712, 6712, 6968,
|
||||||
|
6968, 6968, 7224, 7224, 7480, 7480, 7736, 7736, 7736, 7992, 7992,
|
||||||
|
8248, 8248, 8248, 8504, 8504, 8760, 8760, 8760, 9144, 9144, 9144,
|
||||||
|
9144, 9528, 9528, 9528, 9528, 9912, 9912, 9912,10296,10296,10296,
|
||||||
|
10296,10680,10680,10680,10680,11064,11064,11064,11448,11448,11448},
|
||||||
|
{ 104, 224, 328, 472, 584, 712, 840, 968, 1096, 1224, 1320,
|
||||||
|
1480, 1608, 1672, 1800, 1928, 2088, 2216, 2344, 2472, 2536, 2664,
|
||||||
|
2792, 2984, 3112, 3240, 3368, 3368, 3496, 3624, 3752, 3880, 4008,
|
||||||
|
4136, 4264, 4392, 4584, 4584, 4776, 4968, 4968, 5160, 5352, 5352,
|
||||||
|
5544, 5736, 5736, 5992, 5992, 6200, 6200, 6456, 6456, 6712, 6712,
|
||||||
|
6712, 6968, 6968, 7224, 7224, 7480, 7480, 7736, 7736, 7992, 7992,
|
||||||
|
8248, 8248, 8504, 8504, 8760, 8760, 8760, 9144, 9144, 9144, 9528,
|
||||||
|
9528, 9528, 9912, 9912, 9912,10296,10296,10296,10680,10680,10680,
|
||||||
|
11064,11064,11064,11448,11448,11448,11448,11832,11832,11832,12216,
|
||||||
|
12216,12216,12576,12576,12576,12960,12960,12960,12960,13536,13536},
|
||||||
|
{ 120, 256, 392, 536, 680, 808, 968, 1096, 1256, 1384, 1544,
|
||||||
|
1672, 1800, 1928, 2088, 2216, 2344, 2536, 2664, 2792, 2984, 3112,
|
||||||
|
3240, 3368, 3496, 3624, 3752, 3880, 4008, 4264, 4392, 4584, 4584,
|
||||||
|
4776, 4968, 4968, 5160, 5352, 5544, 5544, 5736, 5992, 5992, 6200,
|
||||||
|
6200, 6456, 6456, 6712, 6968, 6968, 7224, 7224, 7480, 7480, 7736,
|
||||||
|
7736, 7992, 7992, 8248, 8504, 8504, 8760, 8760, 9144, 9144, 9144,
|
||||||
|
9528, 9528, 9528, 9912, 9912, 9912,10296,10296,10680,10680,10680,
|
||||||
|
11064,11064,11064,11448,11448,11448,11832,11832,12216,12216,12216,
|
||||||
|
12576,12576,12576,12960,12960,12960,13536,13536,13536,13536,14112,
|
||||||
|
14112,14112,14112,14688,14688,14688,14688,15264,15264,15264,15264},
|
||||||
|
{ 136, 296, 456, 616, 776, 936, 1096, 1256, 1416, 1544, 1736,
|
||||||
|
1864, 2024, 2216, 2344, 2536, 2664, 2856, 2984, 3112, 3368, 3496,
|
||||||
|
3624, 3752, 4008, 4136, 4264, 4392, 4584, 4776, 4968, 5160, 5160,
|
||||||
|
5352, 5544, 5736, 5736, 5992, 6200, 6200, 6456, 6712, 6712, 6968,
|
||||||
|
6968, 7224, 7480, 7480, 7736, 7992, 7992, 8248, 8248, 8504, 8760,
|
||||||
|
8760, 9144, 9144, 9144, 9528, 9528, 9912, 9912,10296,10296,10296,
|
||||||
|
10680,10680,11064,11064,11064,11448,11448,11832,11832,11832,12216,
|
||||||
|
12216,12576,12576,12960,12960,12960,13536,13536,13536,13536,14112,
|
||||||
|
14112,14112,14112,14688,14688,14688,15264,15264,15264,15264,15840,
|
||||||
|
15840,15840,16416,16416,16416,16416,16992,16992,16992,16992,17568},
|
||||||
|
{ 144, 328, 504, 680, 872, 1032, 1224, 1384, 1544, 1736, 1928,
|
||||||
|
2088, 2280, 2472, 2664, 2792, 2984, 3112, 3368, 3496, 3752, 3880,
|
||||||
|
4008, 4264, 4392, 4584, 4776, 4968, 5160, 5352, 5544, 5736, 5736,
|
||||||
|
5992, 6200, 6200, 6456, 6712, 6712, 6968, 7224, 7480, 7480, 7736,
|
||||||
|
7992, 7992, 8248, 8504, 8504, 8760, 9144, 9144, 9144, 9528, 9528,
|
||||||
|
9912, 9912,10296,10296,10680,10680,11064,11064,11448,11448,11448,
|
||||||
|
11832,11832,12216,12216,12576,12576,12960,12960,12960,13536,13536,
|
||||||
|
13536,14112,14112,14112,14688,14688,14688,14688,15264,15264,15264,
|
||||||
|
15840,15840,15840,16416,16416,16416,16992,16992,16992,16992,17568,
|
||||||
|
17568,17568,18336,18336,18336,18336,18336,19080,19080,19080,19080},
|
||||||
|
{ 176, 376, 584, 776, 1000, 1192, 1384, 1608, 1800, 2024, 2216,
|
||||||
|
2408, 2600, 2792, 2984, 3240, 3496, 3624, 3880, 4008, 4264, 4392,
|
||||||
|
4584, 4776, 4968, 5352, 5544, 5736, 5992, 5992, 6200, 6456, 6712,
|
||||||
|
6968, 6968, 7224, 7480, 7736, 7736, 7992, 8248, 8504, 8760, 8760,
|
||||||
|
9144, 9144, 9528, 9528, 9912, 9912,10296,10680,10680,11064,11064,
|
||||||
|
11448,11448,11832,11832,12216,12216,12576,12576,12960,12960,13536,
|
||||||
|
13536,13536,14112,14112,14112,14688,14688,14688,15264,15264,15840,
|
||||||
|
15840,15840,16416,16416,16416,16992,16992,16992,17568,17568,17568,
|
||||||
|
18336,18336,18336,18336,19080,19080,19080,19080,19848,19848,19848,
|
||||||
|
19848,20616,20616,20616,21384,21384,21384,21384,22152,22152,22152},
|
||||||
|
{ 208, 440, 680, 904, 1128, 1352, 1608, 1800, 2024, 2280, 2472,
|
||||||
|
2728, 2984, 3240, 3368, 3624, 3880, 4136, 4392, 4584, 4776, 4968,
|
||||||
|
5352, 5544, 5736, 5992, 6200, 6456, 6712, 6712, 6968, 7224, 7480,
|
||||||
|
7736, 7992, 8248, 8504, 8760, 8760, 9144, 9528, 9528, 9912, 9912,
|
||||||
|
10296,10680,10680,11064,11064,11448,11832,11832,12216,12216,12576,
|
||||||
|
12576,12960,12960,13536,13536,14112,14112,14112,14688,14688,15264,
|
||||||
|
15264,15264,15840,15840,16416,16416,16416,16992,16992,17568,17568,
|
||||||
|
17568,18336,18336,18336,19080,19080,19080,19080,19848,19848,19848,
|
||||||
|
20616,20616,20616,21384,21384,21384,21384,22152,22152,22152,22920,
|
||||||
|
22920,22920,23688,23688,23688,23688,24496,24496,24496,24496,25456},
|
||||||
|
{ 224, 488, 744, 1000, 1256, 1544, 1800, 2024, 2280, 2536, 2856,
|
||||||
|
3112, 3368, 3624, 3880, 4136, 4392, 4584, 4968, 5160, 5352, 5736,
|
||||||
|
5992, 6200, 6456, 6712, 6968, 7224, 7480, 7736, 7992, 8248, 8504,
|
||||||
|
8760, 9144, 9144, 9528, 9912, 9912,10296,10680,10680,11064,11448,
|
||||||
|
11448,11832,12216,12216,12576,12960,12960,13536,13536,14112,14112,
|
||||||
|
14688,14688,14688,15264,15264,15840,15840,16416,16416,16992,16992,
|
||||||
|
16992,17568,17568,18336,18336,18336,19080,19080,19080,19848,19848,
|
||||||
|
19848,20616,20616,20616,21384,21384,21384,22152,22152,22152,22920,
|
||||||
|
22920,22920,23688,23688,23688,24496,24496,24496,25456,25456,25456,
|
||||||
|
25456,26416,26416,26416,26416,27376,27376,27376,27376,28336,28336},
|
||||||
|
{ 256, 552, 840, 1128, 1416, 1736, 1992, 2280, 2600, 2856, 3112,
|
||||||
|
3496, 3752, 4008, 4264, 4584, 4968, 5160, 5544, 5736, 5992, 6200,
|
||||||
|
6456, 6968, 7224, 7480, 7736, 7992, 8248, 8504, 8760, 9144, 9528,
|
||||||
|
9912, 9912,10296,10680,11064,11064,11448,11832,12216,12216,12576,
|
||||||
|
12960,12960,13536,13536,14112,14112,14688,14688,15264,15264,15840,
|
||||||
|
15840,16416,16416,16992,16992,17568,17568,18336,18336,18336,19080,
|
||||||
|
19080,19848,19848,19848,20616,20616,20616,21384,21384,22152,22152,
|
||||||
|
22152,22920,22920,22920,23688,23688,24496,24496,24496,25456,25456,
|
||||||
|
25456,25456,26416,26416,26416,27376,27376,27376,28336,28336,28336,
|
||||||
|
28336,29296,29296,29296,29296,30576,30576,30576,30576,31704,31704},
|
||||||
|
{ 280, 600, 904, 1224, 1544, 1800, 2152, 2472, 2728, 3112, 3368,
|
||||||
|
3624, 4008, 4264, 4584, 4968, 5160, 5544, 5736, 6200, 6456, 6712,
|
||||||
|
6968, 7224, 7736, 7992, 8248, 8504, 8760, 9144, 9528, 9912,10296,
|
||||||
|
10296,10680,11064,11448,11832,11832,12216,12576,12960,12960,13536,
|
||||||
|
13536,14112,14688,14688,15264,15264,15840,15840,16416,16416,16992,
|
||||||
|
16992,17568,17568,18336,18336,18336,19080,19080,19848,19848,20616,
|
||||||
|
20616,20616,21384,21384,22152,22152,22152,22920,22920,23688,23688,
|
||||||
|
23688,24496,24496,24496,25456,25456,25456,26416,26416,26416,27376,
|
||||||
|
27376,27376,28336,28336,28336,29296,29296,29296,29296,30576,30576,
|
||||||
|
30576,30576,31704,31704,31704,31704,32856,32856,32856,34008,34008},
|
||||||
|
{ 328, 632, 968, 1288, 1608, 1928, 2280, 2600, 2984, 3240, 3624,
|
||||||
|
3880, 4264, 4584, 4968, 5160, 5544, 5992, 6200, 6456, 6712, 7224,
|
||||||
|
7480, 7736, 7992, 8504, 8760, 9144, 9528, 9912, 9912,10296,10680,
|
||||||
|
11064,11448,11832,12216,12216,12576,12960,13536,13536,14112,14112,
|
||||||
|
14688,14688,15264,15840,15840,16416,16416,16992,16992,17568,17568,
|
||||||
|
18336,18336,19080,19080,19848,19848,19848,20616,20616,21384,21384,
|
||||||
|
22152,22152,22152,22920,22920,23688,23688,24496,24496,24496,25456,
|
||||||
|
25456,25456,26416,26416,26416,27376,27376,27376,28336,28336,28336,
|
||||||
|
29296,29296,29296,30576,30576,30576,30576,31704,31704,31704,31704,
|
||||||
|
32856,32856,32856,34008,34008,34008,34008,35160,35160,35160,35160},
|
||||||
|
{ 336, 696, 1064, 1416, 1800, 2152, 2536, 2856, 3240, 3624, 4008,
|
||||||
|
4392, 4776, 5160, 5352, 5736, 6200, 6456, 6712, 7224, 7480, 7992,
|
||||||
|
8248, 8760, 9144, 9528, 9912,10296,10296,10680,11064,11448,11832,
|
||||||
|
12216,12576,12960,13536,13536,14112,14688,14688,15264,15264,15840,
|
||||||
|
16416,16416,16992,17568,17568,18336,18336,19080,19080,19848,19848,
|
||||||
|
20616,20616,20616,21384,21384,22152,22152,22920,22920,23688,23688,
|
||||||
|
24496,24496,24496,25456,25456,26416,26416,26416,27376,27376,27376,
|
||||||
|
28336,28336,29296,29296,29296,30576,30576,30576,30576,31704,31704,
|
||||||
|
31704,32856,32856,32856,34008,34008,34008,35160,35160,35160,35160,
|
||||||
|
36696,36696,36696,36696,37888,37888,37888,39232,39232,39232,39232},
|
||||||
|
{ 376, 776, 1160, 1544, 1992, 2344, 2792, 3112, 3624, 4008, 4392,
|
||||||
|
4776, 5160, 5544, 5992, 6200, 6712, 7224, 7480, 7992, 8248, 8760,
|
||||||
|
9144, 9528, 9912,10296,10680,11064,11448,11832,12216,12576,12960,
|
||||||
|
13536,14112,14112,14688,15264,15264,15840,16416,16416,16992,17568,
|
||||||
|
17568,18336,18336,19080,19080,19848,19848,20616,21384,21384,22152,
|
||||||
|
22152,22920,22920,23688,23688,24496,24496,24496,25456,25456,26416,
|
||||||
|
26416,27376,27376,27376,28336,28336,29296,29296,29296,30576,30576,
|
||||||
|
30576,31704,31704,31704,32856,32856,32856,34008,34008,34008,35160,
|
||||||
|
35160,35160,36696,36696,36696,37888,37888,37888,37888,39232,39232,
|
||||||
|
39232,40576,40576,40576,40576,42368,42368,42368,42368,43816,43816},
|
||||||
|
{ 408, 840, 1288, 1736, 2152, 2600, 2984, 3496, 3880, 4264, 4776,
|
||||||
|
5160, 5544, 5992, 6456, 6968, 7224, 7736, 8248, 8504, 9144, 9528,
|
||||||
|
9912,10296,10680,11064,11448,12216,12576,12960,13536,13536,14112,
|
||||||
|
14688,15264,15264,15840,16416,16992,16992,17568,18336,18336,19080,
|
||||||
|
19080,19848,20616,20616,21384,21384,22152,22152,22920,22920,23688,
|
||||||
|
24496,24496,25456,25456,25456,26416,26416,27376,27376,28336,28336,
|
||||||
|
29296,29296,29296,30576,30576,30576,31704,31704,32856,32856,32856,
|
||||||
|
34008,34008,34008,35160,35160,35160,36696,36696,36696,37888,37888,
|
||||||
|
37888,39232,39232,39232,40576,40576,40576,40576,42368,42368,42368,
|
||||||
|
43816,43816,43816,43816,45352,45352,45352,46888,46888,46888,46888},
|
||||||
|
{ 440, 904, 1384, 1864, 2344, 2792, 3240, 3752, 4136, 4584, 5160,
|
||||||
|
5544, 5992, 6456, 6968, 7480, 7992, 8248, 8760, 9144, 9912,10296,
|
||||||
|
10680,11064,11448,12216,12576,12960,13536,14112,14688,14688,15264,
|
||||||
|
15840,16416,16992,16992,17568,18336,18336,19080,19848,19848,20616,
|
||||||
|
20616,21384,22152,22152,22920,22920,23688,24496,24496,25456,25456,
|
||||||
|
26416,26416,27376,27376,28336,28336,29296,29296,29296,30576,30576,
|
||||||
|
31704,31704,31704,32856,32856,34008,34008,34008,35160,35160,35160,
|
||||||
|
36696,36696,36696,37888,37888,39232,39232,39232,40576,40576,40576,
|
||||||
|
42368,42368,42368,42368,43816,43816,43816,45352,45352,45352,46888,
|
||||||
|
46888,46888,46888,48936,48936,48936,48936,48936,51024,51024,51024},
|
||||||
|
{ 488, 1000, 1480, 1992, 2472, 2984, 3496, 4008, 4584, 4968, 5544,
|
||||||
|
5992, 6456, 6968, 7480, 7992, 8504, 9144, 9528, 9912,10680,11064,
|
||||||
|
11448,12216,12576,12960,13536,14112,14688,15264,15840,15840,16416,
|
||||||
|
16992,17568,18336,18336,19080,19848,19848,20616,21384,21384,22152,
|
||||||
|
22920,22920,23688,24496,24496,25456,25456,26416,26416,27376,27376,
|
||||||
|
28336,28336,29296,29296,30576,30576,31704,31704,31704,32856,32856,
|
||||||
|
34008,34008,35160,35160,35160,36696,36696,36696,37888,37888,39232,
|
||||||
|
39232,39232,40576,40576,40576,42368,42368,42368,43816,43816,43816,
|
||||||
|
45352,45352,45352,46888,46888,46888,46888,48936,48936,48936,48936,
|
||||||
|
51024,51024,51024,51024,52752,52752,52752,52752,55056,55056,55056},
|
||||||
|
{ 520, 1064, 1608, 2152, 2664, 3240, 3752, 4264, 4776, 5352, 5992,
|
||||||
|
6456, 6968, 7480, 7992, 8504, 9144, 9528,10296,10680,11448,11832,
|
||||||
|
12576,12960,13536,14112,14688,15264,15840,16416,16992,16992,17568,
|
||||||
|
18336,19080,19080,19848,20616,21384,21384,22152,22920,22920,23688,
|
||||||
|
24496,24496,25456,25456,26416,27376,27376,28336,28336,29296,29296,
|
||||||
|
30576,30576,31704,31704,32856,32856,34008,34008,34008,35160,35160,
|
||||||
|
36696,36696,36696,37888,37888,39232,39232,40576,40576,40576,42368,
|
||||||
|
42368,42368,43816,43816,43816,45352,45352,45352,46888,46888,46888,
|
||||||
|
48936,48936,48936,48936,51024,51024,51024,51024,52752,52752,52752,
|
||||||
|
55056,55056,55056,55056,57336,57336,57336,57336,59256,59256,59256},
|
||||||
|
{ 552, 1128, 1736, 2280, 2856, 3496, 4008, 4584, 5160, 5736, 6200,
|
||||||
|
6968, 7480, 7992, 8504, 9144, 9912,10296,11064,11448,12216,12576,
|
||||||
|
12960,13536,14112,14688,15264,15840,16416,16992,17568,18336,19080,
|
||||||
|
19848,19848,20616,21384,22152,22152,22920,23688,24496,24496,25456,
|
||||||
|
25456,26416,27376,27376,28336,28336,29296,29296,30576,30576,31704,
|
||||||
|
31704,32856,32856,34008,34008,35160,35160,36696,36696,37888,37888,
|
||||||
|
37888,39232,39232,40576,40576,40576,42368,42368,43816,43816,43816,
|
||||||
|
45352,45352,45352,46888,46888,46888,48936,48936,48936,51024,51024,
|
||||||
|
51024,51024,52752,52752,52752,55056,55056,55056,55056,57336,57336,
|
||||||
|
57336,57336,59256,59256,59256,59256,61664,61664,61664,61664,63776},
|
||||||
|
{ 584, 1192, 1800, 2408, 2984, 3624, 4264, 4968, 5544, 5992, 6712,
|
||||||
|
7224, 7992, 8504, 9144, 9912,10296,11064,11448,12216,12960,13536,
|
||||||
|
14112,14688,15264,15840,16416,16992,17568,18336,19080,19848,19848,
|
||||||
|
20616,21384,22152,22920,22920,23688,24496,25456,25456,26416,26416,
|
||||||
|
27376,28336,28336,29296,29296,30576,31704,31704,32856,32856,34008,
|
||||||
|
34008,35160,35160,36696,36696,36696,37888,37888,39232,39232,40576,
|
||||||
|
40576,42368,42368,42368,43816,43816,45352,45352,45352,46888,46888,
|
||||||
|
46888,48936,48936,48936,51024,51024,51024,52752,52752,52752,52752,
|
||||||
|
55056,55056,55056,57336,57336,57336,57336,59256,59256,59256,61664,
|
||||||
|
61664,61664,61664,63776,63776,63776,63776,66592,66592,66592,66592},
|
||||||
|
{ 616, 1256, 1864, 2536, 3112, 3752, 4392, 5160, 5736, 6200, 6968,
|
||||||
|
7480, 8248, 8760, 9528,10296,10680,11448,12216,12576,13536,14112,
|
||||||
|
14688,15264,15840,16416,16992,17568,18336,19080,19848,20616,20616,
|
||||||
|
21384,22152,22920,23688,24496,24496,25456,26416,26416,27376,28336,
|
||||||
|
28336,29296,29296,30576,31704,31704,32856,32856,34008,34008,35160,
|
||||||
|
35160,36696,36696,37888,37888,39232,39232,40576,40576,40576,42368,
|
||||||
|
42368,43816,43816,43816,45352,45352,46888,46888,46888,48936,48936,
|
||||||
|
48936,51024,51024,51024,52752,52752,52752,55056,55056,55056,55056,
|
||||||
|
57336,57336,57336,59256,59256,59256,61664,61664,61664,61664,63776,
|
||||||
|
63776,63776,63776,66592,66592,66592,66592,68808,68808,68808,71112},
|
||||||
|
{ 712, 1480, 2216, 2984, 3752, 4392, 5160, 5992, 6712, 7480, 8248,
|
||||||
|
8760, 9528,10296,11064,11832,12576,13536,14112,14688,15264,16416,
|
||||||
|
16992,17568,18336,19080,19848,20616,21384,22152,22920,23688,24496,
|
||||||
|
25456,25456,26416,27376,28336,29296,29296,30576,30576,31704,32856,
|
||||||
|
32856,34008,35160,35160,36696,36696,37888,37888,39232,40576,40576,
|
||||||
|
40576,42368,42368,43816,43816,45352,45352,46888,46888,48936,48936,
|
||||||
|
48936,51024,51024,52752,52752,52752,55056,55056,55056,55056,57336,
|
||||||
|
57336,57336,59256,59256,59256,61664,61664,61664,63776,63776,63776,
|
||||||
|
66592,66592,66592,68808,68808,68808,71112,71112,71112,73712,73712,
|
||||||
|
75376,75376,75376,75376,75376,75376,75376,75376,75376,75376,75376}};
|
@ -0,0 +1,105 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* \section COPYRIGHT
|
||||||
|
*
|
||||||
|
* Copyright 2013-2014 The libLTE Developers. See the
|
||||||
|
* COPYRIGHT file at the top-level directory of this distribution.
|
||||||
|
*
|
||||||
|
* \section LICENSE
|
||||||
|
*
|
||||||
|
* This file is part of the libLTE library.
|
||||||
|
*
|
||||||
|
* libLTE 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 3 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* libLTE 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.
|
||||||
|
*
|
||||||
|
* A copy of the GNU Lesser General Public License can be found in
|
||||||
|
* the LICENSE file in the top-level directory of this distribution
|
||||||
|
* and at http://www.gnu.org/licenses/.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <strings.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "lte.h"
|
||||||
|
|
||||||
|
void usage(char *prog) {
|
||||||
|
printf("Usage: %s nof_prb length_bits Word0 Word1 ...\n", prog);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
dci_msg_t msg;
|
||||||
|
ra_pdsch_t ra_dl;
|
||||||
|
ra_pdsch_t ra_ul;
|
||||||
|
int len, rlen;
|
||||||
|
int nof_prb;
|
||||||
|
int nwords;
|
||||||
|
int i;
|
||||||
|
char *y;
|
||||||
|
|
||||||
|
if (argc < 3) {
|
||||||
|
usage(argv[0]);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
nof_prb = atoi(argv[1]);
|
||||||
|
len = atoi(argv[2]);
|
||||||
|
|
||||||
|
nwords = (len-1)/32+1;
|
||||||
|
|
||||||
|
if (argc < 3 + nwords) {
|
||||||
|
usage(argv[0]);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
y = msg.data;
|
||||||
|
rlen = 0;
|
||||||
|
unsigned int x;
|
||||||
|
for (i=0;i<nwords;i++) {
|
||||||
|
x = strtoul(argv[i+3],NULL,16);
|
||||||
|
if (len-rlen < 32) {
|
||||||
|
bit_pack(x, &y, len - rlen);
|
||||||
|
} else {
|
||||||
|
bit_pack(x, &y, 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("DCI message len %d:\n",len);
|
||||||
|
for (i=0;i<len;i++) {
|
||||||
|
printf("%d, ", msg.data[i]);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
dci_msg_type_t dci_type;
|
||||||
|
msg.location.rnti = SIRNTI;
|
||||||
|
msg.location.nof_bits = len;
|
||||||
|
if (dci_msg_get_type(&msg, &dci_type, nof_prb, 1234)) {
|
||||||
|
fprintf(stderr, "Can't obtain DCI message type\n");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
printf("Message type:");
|
||||||
|
dci_msg_type_fprint(stdout, dci_type);
|
||||||
|
switch(dci_type.type) {
|
||||||
|
case PDSCH_SCHED:
|
||||||
|
bzero(&ra_dl, sizeof(ra_pdsch_t));
|
||||||
|
dci_msg_unpack_pdsch(&msg, &ra_dl, nof_prb, false);
|
||||||
|
ra_pdsch_fprint(stdout, &ra_dl, nof_prb);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("Error expected PDSCH\n");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
@ -0,0 +1,309 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* \section COPYRIGHT
|
||||||
|
*
|
||||||
|
* Copyright 2013-2014 The libLTE Developers. See the
|
||||||
|
* COPYRIGHT file at the top-level directory of this distribution.
|
||||||
|
*
|
||||||
|
* \section LICENSE
|
||||||
|
*
|
||||||
|
* This file is part of the libLTE library.
|
||||||
|
*
|
||||||
|
* libLTE 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 3 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* libLTE 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.
|
||||||
|
*
|
||||||
|
* A copy of the GNU Lesser General Public License can be found in
|
||||||
|
* the LICENSE file in the top-level directory of this distribution
|
||||||
|
* and at http://www.gnu.org/licenses/.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <strings.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "lte.h"
|
||||||
|
|
||||||
|
char *input_file_name = NULL;
|
||||||
|
char *matlab_file_name = NULL;
|
||||||
|
int cell_id = 0;
|
||||||
|
int cfi = 2;
|
||||||
|
lte_cp_t cp = CPNORM;
|
||||||
|
int nof_prb = 6;
|
||||||
|
int nof_ports = 1;
|
||||||
|
int flen;
|
||||||
|
unsigned short rnti = SIRNTI;
|
||||||
|
int max_frames = 10;
|
||||||
|
FILE *fmatlab = NULL;
|
||||||
|
|
||||||
|
filesource_t fsrc;
|
||||||
|
pdcch_t pdcch;
|
||||||
|
cf_t *input_buffer, *fft_buffer, *ce[MAX_PORTS_CTRL];
|
||||||
|
regs_t regs;
|
||||||
|
lte_fft_t fft;
|
||||||
|
chest_t chest;
|
||||||
|
dci_t dci_rx;
|
||||||
|
|
||||||
|
void usage(char *prog) {
|
||||||
|
printf("Usage: %s [vcfoe] -i input_file\n", prog);
|
||||||
|
printf("\t-o output matlab file name [Default Disabled]\n");
|
||||||
|
printf("\t-c cell_id [Default %d]\n", cell_id);
|
||||||
|
printf("\t-f cfi [Default %d]\n", cfi);
|
||||||
|
printf("\t-r rnti [Default SI-RNTI]\n");
|
||||||
|
printf("\t-p nof_ports [Default %d]\n", nof_ports);
|
||||||
|
printf("\t-n nof_prb [Default %d]\n", nof_prb);
|
||||||
|
printf("\t-m max_frames [Default %d]\n", max_frames);
|
||||||
|
printf("\t-e Set extended prefix [Default Normal]\n");
|
||||||
|
printf("\t-v [set verbose to debug, default none]\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void parse_args(int argc, char **argv) {
|
||||||
|
int opt;
|
||||||
|
while ((opt = getopt(argc, argv, "irovfcenmp")) != -1) {
|
||||||
|
switch(opt) {
|
||||||
|
case 'i':
|
||||||
|
input_file_name = argv[optind];
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
cell_id = atoi(argv[optind]);
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
rnti = strtoul(argv[optind], NULL, 0);
|
||||||
|
break;
|
||||||
|
case 'm':
|
||||||
|
max_frames = strtoul(argv[optind], NULL, 0);
|
||||||
|
break;
|
||||||
|
case 'f':
|
||||||
|
cfi = atoi(argv[optind]);
|
||||||
|
break;
|
||||||
|
case 'n':
|
||||||
|
nof_prb = atoi(argv[optind]);
|
||||||
|
break;
|
||||||
|
case 'p':
|
||||||
|
nof_ports = atoi(argv[optind]);
|
||||||
|
break;
|
||||||
|
case 'o':
|
||||||
|
matlab_file_name = argv[optind];
|
||||||
|
break;
|
||||||
|
case 'v':
|
||||||
|
verbose++;
|
||||||
|
break;
|
||||||
|
case 'e':
|
||||||
|
cp = CPEXT;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
usage(argv[0]);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!input_file_name) {
|
||||||
|
usage(argv[0]);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int base_init() {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (filesource_init(&fsrc, input_file_name, COMPLEX_FLOAT_BIN)) {
|
||||||
|
fprintf(stderr, "Error opening file %s\n", input_file_name);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (matlab_file_name) {
|
||||||
|
fmatlab = fopen(matlab_file_name, "w");
|
||||||
|
if (!fmatlab) {
|
||||||
|
perror("fopen");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fmatlab = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
flen = 2 * (SLOT_LEN(lte_symbol_sz(nof_prb), cp));
|
||||||
|
|
||||||
|
input_buffer = malloc(flen * sizeof(cf_t));
|
||||||
|
if (!input_buffer) {
|
||||||
|
perror("malloc");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
fft_buffer = malloc(CP_NSYMB(cp) * nof_prb * RE_X_RB * sizeof(cf_t));
|
||||||
|
if (!fft_buffer) {
|
||||||
|
perror("malloc");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i=0;i<MAX_PORTS_CTRL;i++) {
|
||||||
|
ce[i] = malloc(CP_NSYMB(cp) * nof_prb * RE_X_RB * sizeof(cf_t));
|
||||||
|
if (!ce[i]) {
|
||||||
|
perror("malloc");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chest_init(&chest, LINEAR, cp, nof_prb, nof_ports)) {
|
||||||
|
fprintf(stderr, "Error initializing equalizer\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chest_ref_LTEDL(&chest, cell_id)) {
|
||||||
|
fprintf(stderr, "Error initializing reference signal\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lte_fft_init(&fft, cp, nof_prb)) {
|
||||||
|
fprintf(stderr, "Error initializing FFT\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (regs_init(®s, cell_id, nof_prb, nof_ports, R_1, PHICH_NORM, cp)) {
|
||||||
|
fprintf(stderr, "Error initiating regs\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (regs_set_cfi(®s, cfi)) {
|
||||||
|
fprintf(stderr, "Error setting CFI %d\n", cfi);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pdcch_init(&pdcch, ®s, nof_prb, nof_ports, cell_id, cp)) {
|
||||||
|
fprintf(stderr, "Error creating PDCCH object\n");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
dci_init(&dci_rx, 10);
|
||||||
|
|
||||||
|
DEBUG("Memory init OK\n",0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void base_free() {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
filesource_free(&fsrc);
|
||||||
|
if (fmatlab) {
|
||||||
|
fclose(fmatlab);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(input_buffer);
|
||||||
|
free(fft_buffer);
|
||||||
|
|
||||||
|
filesource_free(&fsrc);
|
||||||
|
for (i=0;i<MAX_PORTS_CTRL;i++) {
|
||||||
|
free(ce[i]);
|
||||||
|
}
|
||||||
|
chest_free(&chest);
|
||||||
|
lte_fft_free(&fft);
|
||||||
|
|
||||||
|
dci_free(&dci_rx);
|
||||||
|
pdcch_free(&pdcch);
|
||||||
|
regs_free(®s);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
ra_pdsch_t ra_dl;
|
||||||
|
int i;
|
||||||
|
int nof_dcis;
|
||||||
|
int nof_frames;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (argc < 3) {
|
||||||
|
usage(argv[0]);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
parse_args(argc,argv);
|
||||||
|
|
||||||
|
if (base_init()) {
|
||||||
|
fprintf(stderr, "Error initializing memory\n");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rnti == SIRNTI) {
|
||||||
|
INFO("Initializing common search space for SI-RNTI\n",0);
|
||||||
|
pdcch_init_search_si(&pdcch);
|
||||||
|
} else {
|
||||||
|
INFO("Initializing user-specific search space for RNTI: 0x%x\n", rnti);
|
||||||
|
pdcch_init_search_ue(&pdcch, rnti);
|
||||||
|
}
|
||||||
|
ret = -1;
|
||||||
|
nof_frames = 0;
|
||||||
|
do {
|
||||||
|
filesource_read(&fsrc, input_buffer, flen);
|
||||||
|
if (nof_frames == 5) {
|
||||||
|
INFO("Reading %d samples sub-frame %d\n", flen, nof_frames);
|
||||||
|
|
||||||
|
lte_fft_run(&fft, input_buffer, fft_buffer);
|
||||||
|
|
||||||
|
if (fmatlab) {
|
||||||
|
fprintf(fmatlab, "infft%d=", nof_frames);
|
||||||
|
vec_fprint_c(fmatlab, input_buffer, flen);
|
||||||
|
fprintf(fmatlab, ";\n");
|
||||||
|
|
||||||
|
fprintf(fmatlab, "outfft%d=", nof_frames);
|
||||||
|
vec_sc_prod_cfc(fft_buffer, 1000.0, fft_buffer, CP_NSYMB(cp) * nof_prb * RE_X_RB);
|
||||||
|
vec_fprint_c(fmatlab, fft_buffer, CP_NSYMB(cp) * nof_prb * RE_X_RB);
|
||||||
|
fprintf(fmatlab, ";\n");
|
||||||
|
vec_sc_prod_cfc(fft_buffer, 0.001, fft_buffer, CP_NSYMB(cp) * nof_prb * RE_X_RB);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get channel estimates for each port */
|
||||||
|
for (i=0;i<nof_ports;i++) {
|
||||||
|
chest_ce_slot_port(&chest, fft_buffer, ce[i], 2*nof_frames, i);
|
||||||
|
if (fmatlab) {
|
||||||
|
chest_fprint(&chest, fmatlab, 2*nof_frames, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nof_dcis = pdcch_decode(&pdcch, fft_buffer, ce, &dci_rx, nof_frames%10, 1);
|
||||||
|
|
||||||
|
INFO("Received %d DCI messages\n", nof_dcis);
|
||||||
|
|
||||||
|
for (i=0;i<nof_dcis;i++) {
|
||||||
|
dci_msg_type_t type;
|
||||||
|
if (dci_msg_get_type(&dci_rx.msg[i], &type, nof_prb, 1234)) {
|
||||||
|
fprintf(stderr, "Can't get DCI message type\n");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
printf("MSG %d: ",i);
|
||||||
|
dci_msg_type_fprint(stdout, type);
|
||||||
|
switch(type.type) {
|
||||||
|
case PDSCH_SCHED:
|
||||||
|
bzero(&ra_dl, sizeof(ra_pdsch_t));
|
||||||
|
if (dci_msg_unpack_pdsch(&dci_rx.msg[i], &ra_dl, nof_prb, rnti != SIRNTI)) {
|
||||||
|
fprintf(stderr, "Can't unpack PDSCH message\n");
|
||||||
|
} else {
|
||||||
|
ra_pdsch_fprint(stdout, &ra_dl, nof_prb);
|
||||||
|
if (ra_dl.alloc_type == alloc_type2 && ra_dl.type2_alloc.mode == t2_loc
|
||||||
|
&& ra_dl.type2_alloc.riv == 11 && ra_dl.rv_idx == 0
|
||||||
|
&& ra_dl.harq_process == 0 && ra_dl.mcs.mcs_idx == 2) {
|
||||||
|
printf("This is the file signal.1.92M.amar.dat\n");
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "Unsupported message type\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
nof_frames++;
|
||||||
|
} while (nof_frames <= max_frames);
|
||||||
|
|
||||||
|
base_free();
|
||||||
|
fftwf_cleanup();
|
||||||
|
exit(ret);
|
||||||
|
}
|
Binary file not shown.
@ -1,33 +0,0 @@
|
|||||||
#
|
|
||||||
# Copyright 2012-2013 The libLTE Developers. See the
|
|
||||||
# COPYRIGHT file at the top-level directory of this distribution.
|
|
||||||
#
|
|
||||||
# This file is part of the libLTE library.
|
|
||||||
#
|
|
||||||
# libLTE 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 3 of
|
|
||||||
# the License, or (at your option) any later version.
|
|
||||||
#
|
|
||||||
# libLTE 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.
|
|
||||||
#
|
|
||||||
# A copy of the GNU Lesser General Public License can be found in
|
|
||||||
# the LICENSE file in the top-level directory of this distribution
|
|
||||||
# and at http://www.gnu.org/licenses/.
|
|
||||||
#
|
|
||||||
|
|
||||||
########################################################################
|
|
||||||
# RATEMATCHING TEST
|
|
||||||
########################################################################
|
|
||||||
|
|
||||||
ADD_EXECUTABLE(rm_conv_test rm_conv_test.c)
|
|
||||||
TARGET_LINK_LIBRARIES(rm_conv_test lte)
|
|
||||||
|
|
||||||
ADD_TEST(rm_conv_test_1 rm_conv_test -t 480 -r 1920)
|
|
||||||
ADD_TEST(rm_conv_test_2 rm_conv_test -t 1920 -r 480)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue