Added PDCCH encoder/decoder. Tested with Amarisoft eNodeB

master
ismagom 11 years ago
parent 7f42343215
commit c40d1e5dbf

@ -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,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(&regs, cell_id, nof_prb, nof_ports, R_1, PHICH_NORM, cp)) {
fprintf(stderr, "Error initiating regs\n");
return -1;
}
if (regs_set_cfi(&regs, cfi)) {
fprintf(stderr, "Error setting CFI %d\n", cfi);
return -1;
}
if (pdcch_init(&pdcch, &regs, 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(&regs);
}
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);
}
Loading…
Cancel
Save