Fixed PDSCH bugs. Cleaned MCS interface in RA. Converted MODEM module to stdint

master
ismagom 11 years ago
parent 01ca2dcf28
commit 09243c7996

@ -48,6 +48,7 @@ lte_cell_t cell = {
}; };
uint32_t cfi=1; uint32_t cfi=1;
uint32_t mcs_idx = 12;
int nof_frames = -1; int nof_frames = -1;
char *uhd_args = ""; char *uhd_args = "";
@ -70,12 +71,12 @@ void usage(char *prog) {
#ifndef DISABLE_UHD #ifndef DISABLE_UHD
printf("\t-a UHD args [Default %s]\n", uhd_args); printf("\t-a UHD args [Default %s]\n", uhd_args);
printf("\t-g UHD TX gain [Default %.2f dB]\n", uhd_gain); printf("\t-g UHD TX gain [Default %.2f dB]\n", uhd_gain);
printf("\t-m UHD signal amplitude [Default %.2f]\n", uhd_amp);
printf("\t-f UHD TX frequency [Default %.1f MHz]\n", uhd_freq / 1000000); printf("\t-f UHD TX frequency [Default %.1f MHz]\n", uhd_freq / 1000000);
#else #else
printf("\t UHD is disabled. CUHD library not available\n"); printf("\t UHD is disabled. CUHD library not available\n");
#endif #endif
printf("\t-o output_file [Default USRP]\n"); printf("\t-o output_file [Default USRP]\n");
printf("\t-m MCS index [Default %d]\n", mcs_idx);
printf("\t-n number of frames [Default %d]\n", nof_frames); printf("\t-n number of frames [Default %d]\n", nof_frames);
printf("\t-c cell id [Default %d]\n", cell.id); printf("\t-c cell id [Default %d]\n", cell.id);
printf("\t-p nof_prb [Default %d]\n", cell.nof_prb); printf("\t-p nof_prb [Default %d]\n", cell.nof_prb);
@ -92,15 +93,15 @@ void parse_args(int argc, char **argv) {
case 'g': case 'g':
uhd_gain = atof(argv[optind]); uhd_gain = atof(argv[optind]);
break; break;
case 'm':
uhd_amp = atof(argv[optind]);
break;
case 'f': case 'f':
uhd_freq = atof(argv[optind]); uhd_freq = atof(argv[optind]);
break; break;
case 'o': case 'o':
output_file_name = argv[optind]; output_file_name = argv[optind];
break; break;
case 'm':
mcs_idx = atoi(argv[optind]);
break;
case 'n': case 'n':
nof_frames = atoi(argv[optind]); nof_frames = atoi(argv[optind]);
break; break;
@ -289,7 +290,7 @@ int main(int argc, char **argv) {
bzero(&ra_dl, sizeof(ra_pdsch_t)); bzero(&ra_dl, sizeof(ra_pdsch_t));
ra_dl.harq_process = 0; ra_dl.harq_process = 0;
ra_pdsch_set_mcs(&ra_dl, QPSK, 5); ra_dl.mcs_idx = mcs_idx;
ra_dl.ndi = 0; ra_dl.ndi = 0;
ra_dl.rv_idx = 0; ra_dl.rv_idx = 0;
ra_dl.alloc_type = alloc_type0; ra_dl.alloc_type = alloc_type0;
@ -299,7 +300,7 @@ int main(int argc, char **argv) {
ra_prb_get_dl(&prb_alloc, &ra_dl, cell.nof_prb); ra_prb_get_dl(&prb_alloc, &ra_dl, cell.nof_prb);
ra_prb_get_re_dl(&prb_alloc, cell.nof_prb, 1, cell.nof_prb<10?(cfi+1):cfi, CPNORM); ra_prb_get_re_dl(&prb_alloc, cell.nof_prb, 1, cell.nof_prb<10?(cfi+1):cfi, CPNORM);
ra_dl.mcs.tbs = ra_tbs_from_idx(ra_dl.mcs.tbs_idx, cell.nof_prb); ra_mcs_from_idx_dl(mcs_idx, cell.nof_prb, &ra_dl.mcs);
ra_pdsch_fprint(stdout, &ra_dl, cell.nof_prb); ra_pdsch_fprint(stdout, &ra_dl, cell.nof_prb);
@ -322,7 +323,7 @@ int main(int argc, char **argv) {
} }
while (nf < nof_frames || nof_frames == -1) { while (nf < nof_frames || nof_frames == -1) {
for (sf_idx = 0; sf_idx < NSUBFRAMES_X_FRAME; sf_idx++) { for (sf_idx = 0; sf_idx < NSUBFRAMES_X_FRAME && (nf < nof_frames || nof_frames == -1); sf_idx++) {
bzero(sf_buffer, sizeof(cf_t) * sf_n_re); bzero(sf_buffer, sizeof(cf_t) * sf_n_re);
if (sf_idx == 0 || sf_idx == 5) { if (sf_idx == 0 || sf_idx == 5) {
@ -346,6 +347,7 @@ int main(int argc, char **argv) {
data[i] = rand()%2; data[i] = rand()%2;
} }
INFO("Puttting DCI to location: n=%d, L=%d\n", locations[sf_idx][0].ncce, locations[sf_idx][0].L);
if (pdcch_encode(&pdcch, &dci_msg, locations[sf_idx][0], 1234, sf_symbols, sf_idx, cfi)) { if (pdcch_encode(&pdcch, &dci_msg, locations[sf_idx][0], 1234, sf_symbols, sf_idx, cfi)) {
fprintf(stderr, "Error encoding DCI message\n"); fprintf(stderr, "Error encoding DCI message\n");
exit(-1); exit(-1);
@ -366,11 +368,11 @@ int main(int argc, char **argv) {
cuhd_send(uhd, output_buffer, sf_n_samples, 1); cuhd_send(uhd, output_buffer, sf_n_samples, 1);
#endif #endif
} }
nf++;
} }
mib.sfn = (mib.sfn + 1) % 1024; mib.sfn = (mib.sfn + 1) % 1024;
printf("SFN: %4d\r", mib.sfn); printf("SFN: %4d\r", mib.sfn);
fflush(stdout); fflush(stdout);
nf++;
} }
base_free(); base_free();

@ -398,11 +398,10 @@ int cell_id_init(int nof_prb, int cell_id) {
char data[10000]; char data[10000];
int rx_run(cf_t *input, int sf_idx) { int pdsch_run(cf_t *input, uint32_t sf_idx) {
uint32_t cfi, cfi_distance, i; uint32_t cfi, cfi_distance, i;
cf_t *input_decim; cf_t *input_decim;
ra_pdsch_t ra_dl; ra_pdsch_t ra_dl;
ra_prb_t prb_alloc;
dci_location_t locations[10]; dci_location_t locations[10];
dci_msg_t dci_msg; dci_msg_t dci_msg;
uint32_t nof_locations; uint32_t nof_locations;
@ -422,6 +421,7 @@ int rx_run(cf_t *input, int sf_idx) {
/* First decode PCFICH and obtain CFI */ /* First decode PCFICH and obtain CFI */
if (pcfich_decode(&pcfich, fft_buffer, ce, sf_idx, &cfi, &cfi_distance)<0) { if (pcfich_decode(&pcfich, fft_buffer, ce, sf_idx, &cfi, &cfi_distance)<0) {
fprintf(stderr, "Error decoding PCFICH\n");
return -1; return -1;
} }
@ -441,56 +441,27 @@ int rx_run(cf_t *input, int sf_idx) {
fprintf(stderr, "Error extracting LLRs\n"); fprintf(stderr, "Error extracting LLRs\n");
return -1; return -1;
} }
if (pdcch_decode_msg(&pdcch, &dci_msg, Format1A, &crc_rem)) { if (pdcch_decode_msg(&pdcch, &dci_msg, Format1, &crc_rem)) {
fprintf(stderr, "Error decoding DCI msg\n"); fprintf(stderr, "Error decoding DCI msg\n");
return -1; return -1;
} }
} }
if (crc_rem == 1234) { if (crc_rem == 1234) {
dci_msg_type_t type; if (dci_msg_to_ra_dl(&dci_msg, 1234, 1234, cell, cfi, &ra_dl)) {
if (dci_msg_get_type(&dci_msg, &type, cell.nof_prb, 1234, 1234)) { fprintf(stderr, "Error unpacking PDSCH scheduling DCI message\n");
fprintf(stderr, "Can't get DCI message type\n"); return -1;
} else {
if (VERBOSE_ISINFO()) {
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_msg, &ra_dl, cell.nof_prb,
false)) {
fprintf(stderr, "Can't unpack PDSCH message\n");
break;
}
if (VERBOSE_ISINFO() || !pkts_total) {
printf("\n");
ra_pdsch_fprint(stdout, &ra_dl, cell.nof_prb);
printf("\n");
}
if (ra_prb_get_dl(&prb_alloc, &ra_dl, cell.nof_prb)) {
fprintf(stderr, "Error computing resource allocation\n");
break;
} }
ra_prb_get_re_dl(&prb_alloc, cell.nof_prb, cell.nof_ports,
cell.nof_prb<10?(cfi+1):cfi, CPNORM);
if (pdsch_harq_setup(&harq_process, ra_dl.mcs, &prb_alloc)) { if (pdsch_harq_setup(&harq_process, ra_dl.mcs, &ra_dl.prb_alloc)) {
fprintf(stderr, "Error configuring HARQ process\n"); fprintf(stderr, "Error configuring HARQ process\n");
break; return -1;
} }
if (pdsch_decode(&pdsch, fft_buffer, ce, data, sf_idx, &harq_process, ra_dl.rv_idx)) { if (pdsch_decode(&pdsch, fft_buffer, ce, data, sf_idx, &harq_process, ra_dl.rv_idx)) {
pkt_errors++; pkt_errors++;
} }
pkts_total++; pkts_total++;
break;
default:
fprintf(stderr, "Unsupported message type\n");
break;
}
}
} }
#ifndef DISABLE_GRAPHICS #ifndef DISABLE_GRAPHICS
@ -504,8 +475,8 @@ int rx_run(cf_t *input, int sf_idx) {
} }
plot_real_setNewData(&poutfft, tmp_plot, n_re); plot_real_setNewData(&poutfft, tmp_plot, n_re);
plot_complex_setNewData(&pce, ce[0], n_re); plot_complex_setNewData(&pce, ce[0], n_re);
plot_scatter_setNewData(&pscatrecv, pdsch.pdsch_symbols[0], prb_alloc.re_sf[sf_idx]); plot_scatter_setNewData(&pscatrecv, pdsch.pdsch_symbols[0], ra_dl.prb_alloc.re_sf[sf_idx]);
plot_scatter_setNewData(&pscatequal, pdsch.pdsch_d, prb_alloc.re_sf[sf_idx]); plot_scatter_setNewData(&pscatequal, pdsch.pdsch_d, ra_dl.prb_alloc.re_sf[sf_idx]);
} }
#endif #endif
@ -574,7 +545,8 @@ int run_receiver(cf_t *input, uint32_t cell_id, uint32_t sf_idx) {
} }
} }
if (cell.nof_prb && !pbch_only) { if (cell.nof_prb && !pbch_only) {
if (rx_run(input, sf_idx)) { if (pdsch_run(input, sf_idx)) {
fprintf(stderr, "\nError running PDSCH decoder\n");
return -1; return -1;
} }
} }
@ -665,20 +637,22 @@ int main(int argc, char **argv) {
sync_frame_set_threshold(&sframe, find_threshold); sync_frame_set_threshold(&sframe, find_threshold);
while (!go_exit && (frame_cnt < nof_frames || nof_frames == -1)) {
read_io(input_buffer, sf_n_samples);
if (input_file_name) {
ret = 1;
sf_idx = 0; sf_idx = 0;
cell_id = cell_id_file; cell_id = cell_id_file;
if (input_file_name) {
in_ptr = input_buffer; in_ptr = input_buffer;
} else { } else {
ret = sync_frame_push(&sframe, input_buffer, sf_buffer);
in_ptr = sf_buffer; in_ptr = sf_buffer;
cell_id = 0; }
sf_idx = 0;
while (!go_exit && (frame_cnt < nof_frames || nof_frames == -1)) {
read_io(input_buffer, sf_n_samples);
if (!input_file_name) {
ret = sync_frame_push(&sframe, input_buffer, sf_buffer);
} else {
ret = 1;
} }
switch(ret ) { switch(ret ) {
case 0: case 0:
@ -698,6 +672,7 @@ int main(int argc, char **argv) {
/* synch'd and tracking */ /* synch'd and tracking */
if (run_receiver(in_ptr, cell_id, sf_idx)) { if (run_receiver(in_ptr, cell_id, sf_idx)) {
fprintf(stderr, "\nError running receiver\n");fflush(stdout);
exit(-1); exit(-1);
} }
@ -708,7 +683,9 @@ int main(int argc, char **argv) {
(float) pkt_errors / pkts_total); (float) pkt_errors / pkts_total);
fflush(stdout); fflush(stdout);
} }
if (input_file_name) {
sf_idx++;
}
break; break;
default: default:
fprintf(stderr, "Error running automatic synchronization\n"); fprintf(stderr, "Error running automatic synchronization\n");

@ -120,6 +120,10 @@ typedef enum LIBLTE_API {
typedef enum LIBLTE_API { PHICH_NORM, PHICH_EXT} phich_length_t; typedef enum LIBLTE_API { PHICH_NORM, PHICH_EXT} phich_length_t;
typedef enum LIBLTE_API { R_1_6, R_1_2, R_1, R_2} phich_resources_t; typedef enum LIBLTE_API { R_1_6, R_1_2, R_1, R_2} phich_resources_t;
typedef enum LIBLTE_API {
LTE_BPSK = 1, LTE_QPSK = 2, LTE_QAM16 = 4, LTE_QAM64 = 6
} lte_mod_t;
typedef struct LIBLTE_API { typedef struct LIBLTE_API {
int id; int id;
@ -147,6 +151,10 @@ LIBLTE_API uint32_t lte_voffset(uint32_t symbol_id,
LIBLTE_API int lte_cb_size(uint32_t index); LIBLTE_API int lte_cb_size(uint32_t index);
LIBLTE_API char *lte_mod_string(lte_mod_t mod);
LIBLTE_API uint32_t lte_mod_bits_x_symbol(lte_mod_t mod);
LIBLTE_API int lte_find_cb_index(uint32_t long_cb); LIBLTE_API int lte_find_cb_index(uint32_t long_cb);
LIBLTE_API float lte_band_fd(uint32_t earfcn); LIBLTE_API float lte_band_fd(uint32_t earfcn);

@ -38,13 +38,13 @@
typedef _Complex float cf_t; typedef _Complex float cf_t;
typedef struct LIBLTE_API { typedef struct LIBLTE_API {
enum modem_std table; /* In this implementation, mapping table is hard-coded */ lte_mod_t mod; /* In this implementation, mapping table is hard-coded */
}demod_hard_t; }demod_hard_t;
LIBLTE_API void demod_hard_init(demod_hard_t* q); LIBLTE_API void demod_hard_init(demod_hard_t* q);
LIBLTE_API void demod_hard_table_set(demod_hard_t* q, enum modem_std table); LIBLTE_API void demod_hard_table_set(demod_hard_t* q, lte_mod_t mod);
LIBLTE_API int demod_hard_demodulate(demod_hard_t* q, cf_t* symbols, char *bits, int nsymbols); LIBLTE_API int demod_hard_demodulate(demod_hard_t* q, cf_t* symbols, char *bits, uint32_t nsymbols);
@ -52,7 +52,7 @@ LIBLTE_API int demod_hard_demodulate(demod_hard_t* q, cf_t* symbols, char *bits,
typedef struct LIBLTE_API { typedef struct LIBLTE_API {
demod_hard_t obj; demod_hard_t obj;
struct demod_hard_init { struct demod_hard_init {
enum modem_std std; // Symbol mapping standard (see modem_table.h) lte_mod_t std; // Symbol mapping standard (see modem_table.h)
} init; } init;
cf_t* input; cf_t* input;

@ -56,7 +56,7 @@ typedef struct LIBLTE_API {
modem_table_t table; modem_table_t table;
struct demod_soft_init{ struct demod_soft_init{
enum modem_std std; // symbol mapping standard (see modem_table.h) lte_mod_t std; // symbol mapping standard (see modem_table.h)
} init; } init;
const cf_t* input; const cf_t* input;

@ -37,13 +37,13 @@
typedef _Complex float cf_t; typedef _Complex float cf_t;
LIBLTE_API int mod_modulate(modem_table_t* table, const char *bits, cf_t* symbols, int nbits); LIBLTE_API int mod_modulate(modem_table_t* table, const char *bits, cf_t* symbols, uint32_t nbits);
/* High-level API */ /* High-level API */
typedef struct LIBLTE_API { typedef struct LIBLTE_API {
modem_table_t obj; modem_table_t obj;
struct mod_init { struct mod_init {
enum modem_std std; // symbol mapping standard (see modem_table.h) lte_mod_t std; // symbol mapping standard (see modem_table.h)
} init; } init;
const char* input; const char* input;

@ -34,30 +34,36 @@
#include <complex.h> #include <complex.h>
#include <stdint.h> #include <stdint.h>
#include "liblte/phy/common/phy_common.h"
#include "liblte/config.h" #include "liblte/config.h"
typedef _Complex float cf_t; typedef _Complex float cf_t;
typedef struct LIBLTE_API { typedef struct LIBLTE_API {
int idx[2][6][32]; uint32_t idx[2][6][32];
}soft_table_t; }soft_table_t;
typedef struct LIBLTE_API { typedef struct LIBLTE_API {
cf_t* symbol_table; // bit-to-symbol mapping cf_t* symbol_table; // bit-to-symbol mapping
soft_table_t soft_table; // symbol-to-bit mapping (used in soft demodulating) soft_table_t soft_table; // symbol-to-bit mapping (used in soft demodulating)
int nsymbols; // number of modulation symbols uint32_t nsymbols; // number of modulation symbols
int nbits_x_symbol; // number of bits per symbol uint32_t nbits_x_symbol; // number of bits per symbol
}modem_table_t; }modem_table_t;
// Modulation standards
enum modem_std {
LTE_BPSK = 1, LTE_QPSK = 2, LTE_QAM16 = 4, LTE_QAM64 = 6
};
LIBLTE_API void modem_table_init(modem_table_t* q); LIBLTE_API void modem_table_init(modem_table_t* q);
LIBLTE_API void modem_table_free(modem_table_t* q); LIBLTE_API void modem_table_free(modem_table_t* q);
LIBLTE_API void modem_table_reset(modem_table_t* q); LIBLTE_API void modem_table_reset(modem_table_t* q);
LIBLTE_API int modem_table_set(modem_table_t* q, cf_t* table, soft_table_t *soft_table, int nsymbols, int nbits_x_symbol);
LIBLTE_API int modem_table_std(modem_table_t* q, enum modem_std table, bool compute_soft_demod); LIBLTE_API int modem_table_set(modem_table_t* q,
cf_t* table,
soft_table_t *soft_table,
uint32_t nsymbols,
uint32_t nbits_x_symbol);
LIBLTE_API int modem_table_lte(modem_table_t* q,
lte_mod_t modulation,
bool compute_soft_demod);
#endif // MODEM_TABLE_ #endif // MODEM_TABLE_

@ -71,7 +71,24 @@ typedef struct LIBLTE_API {
uint32_t nof_bits; uint32_t nof_bits;
} dci_msg_t; } dci_msg_t;
/* Converts a received PDSCH DL scheduling DCI message
* to ra structures ready to be passed to the harq setup function
*/
LIBLTE_API int dci_msg_to_ra_dl(dci_msg_t *msg,
uint16_t msg_rnti,
uint16_t c_rnti,
lte_cell_t cell,
uint32_t cfi,
ra_pdsch_t *ra_dl);
/* TODO
LIBLTE_API int dci_msg_to_ra_ul(dci_msg_t *msg,
uint16_t msg_rnti,
uint16_t c_rnti,
lte_cell_t cell,
uint32_t cfi,
ra_pusch_t *ra_ul);
*/
LIBLTE_API char* dci_format_string(dci_format_t format); LIBLTE_API char* dci_format_string(dci_format_t format);
LIBLTE_API int dci_location_set(dci_location_t *c, LIBLTE_API int dci_location_set(dci_location_t *c,

@ -57,7 +57,6 @@ typedef struct LIBLTE_API {
float **pdsch_w_buff_f; float **pdsch_w_buff_f;
char **pdsch_w_buff_c; char **pdsch_w_buff_c;
struct cb_segm { struct cb_segm {
uint32_t F; uint32_t F;
uint32_t C; uint32_t C;
@ -82,8 +81,8 @@ typedef struct LIBLTE_API {
cf_t *pdsch_symbols[MAX_PORTS]; cf_t *pdsch_symbols[MAX_PORTS];
cf_t *pdsch_x[MAX_PORTS]; cf_t *pdsch_x[MAX_PORTS];
cf_t *pdsch_d; cf_t *pdsch_d;
void *cb_in; char *cb_in;
char *cb_out; void *cb_out;
void *pdsch_e; void *pdsch_e;
/* tx & rx objects */ /* tx & rx objects */

@ -37,17 +37,9 @@
* allocation. * allocation.
*/ */
typedef enum LIBLTE_API {
MOD_NULL = 0, BPSK = 1, QPSK = 2, QAM16 = 3, QAM64 = 4
} ra_mod_t;
typedef struct LIBLTE_API { typedef struct LIBLTE_API {
ra_mod_t mod; // By default, mod = MOD_NULL and the mcs_idx value is taken by the packing functions lte_mod_t mod;
// otherwise mod + tbs values are used to generate the mcs_idx automatically. uint32_t tbs;
uint32_t tbs_idx;
uint32_t mcs_idx;
uint32_t 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; } ra_mcs_t;
typedef enum LIBLTE_API { typedef enum LIBLTE_API {
@ -60,7 +52,8 @@ typedef struct LIBLTE_API {
typedef struct LIBLTE_API { typedef struct LIBLTE_API {
uint32_t vrb_bitmask; uint32_t vrb_bitmask;
uint32_t rbg_subset;bool shift; uint32_t rbg_subset;
bool shift;
} ra_type1_t; } ra_type1_t;
typedef struct LIBLTE_API { typedef struct LIBLTE_API {
@ -78,6 +71,17 @@ typedef struct LIBLTE_API {
} mode; } mode;
} ra_type2_t; } ra_type2_t;
typedef struct LIBLTE_API {
uint32_t prb_idx[MAX_PRB];
uint32_t nof_prb;
} ra_prb_slot_t;
typedef struct LIBLTE_API {
ra_prb_slot_t slot[2];
uint32_t lstart;
uint32_t re_sf[NSUBFRAMES_X_FRAME];
} ra_prb_t;
typedef struct LIBLTE_API { typedef struct LIBLTE_API {
uint16_t rnti; uint16_t rnti;
ra_type_t alloc_type; ra_type_t alloc_type;
@ -86,6 +90,8 @@ typedef struct LIBLTE_API {
ra_type1_t type1_alloc; ra_type1_t type1_alloc;
ra_type2_t type2_alloc; ra_type2_t type2_alloc;
}; };
ra_prb_t prb_alloc;
uint32_t mcs_idx;
ra_mcs_t mcs; ra_mcs_t mcs;
uint32_t harq_process; uint32_t harq_process;
uint32_t rv_idx; uint32_t rv_idx;
@ -93,7 +99,7 @@ typedef struct LIBLTE_API {
} ra_pdsch_t; } ra_pdsch_t;
typedef struct LIBLTE_API { typedef struct LIBLTE_API {
/* 36.213 Table 8.4-2: hop_half is 0 for < 10 Mhz and 10 for > 10 Mh. /* 36.213 Table 8.4-2: hop_half is 0 for < 10 Mhz and 10 for > 10 Mhz.
* hop_quart is 00 for > 10 Mhz and hop_quart_neg is 01 for > 10 Mhz. * hop_quart is 00 for > 10 Mhz and hop_quart_neg is 01 for > 10 Mhz.
*/ */
enum { enum {
@ -104,7 +110,10 @@ typedef struct LIBLTE_API {
hop_type_2 = 3 hop_type_2 = 3
} freq_hop_fl; } freq_hop_fl;
ra_prb_t prb_alloc;
ra_type2_t type2_alloc; ra_type2_t type2_alloc;
uint32_t mcs_idx;
ra_mcs_t mcs; ra_mcs_t mcs;
uint32_t rv_idx; // If set to non-zero, a retransmission is requested with the same modulation uint32_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). // than before (Format0 message, see also 8.6.1 in 36.2313).
@ -113,17 +122,6 @@ typedef struct LIBLTE_API {
} ra_pusch_t; } ra_pusch_t;
typedef struct LIBLTE_API {
uint32_t prb_idx[MAX_PRB];
uint32_t nof_prb;
} ra_prb_slot_t;
typedef struct LIBLTE_API {
ra_prb_slot_t slot[2];
uint32_t lstart;
uint32_t re_sf[NSUBFRAMES_X_FRAME];
} ra_prb_t;
LIBLTE_API void ra_prb_fprint(FILE *f, LIBLTE_API void ra_prb_fprint(FILE *f,
ra_prb_slot_t *prb); ra_prb_slot_t *prb);
@ -147,36 +145,22 @@ LIBLTE_API uint32_t ra_nprb_dl(ra_pdsch_t *ra,
LIBLTE_API uint32_t ra_nprb_ul(ra_pusch_t *ra, LIBLTE_API uint32_t ra_nprb_ul(ra_pusch_t *ra,
uint32_t nof_prb); uint32_t nof_prb);
LIBLTE_API uint32_t ra_mod_bits_x_symbol(ra_mod_t mod); LIBLTE_API int ra_mcs_from_idx_dl(uint32_t mcs_idx,
uint32_t nof_prb,
LIBLTE_API uint32_t ra_mcs_to_table_idx(ra_mcs_t *mcs);
LIBLTE_API int ra_mcs_from_idx_dl(uint32_t idx,
ra_mcs_t *mcs); ra_mcs_t *mcs);
LIBLTE_API int ra_mcs_from_idx_ul(uint32_t idx, LIBLTE_API int ra_mcs_from_idx_ul(uint32_t mcs_idx,
uint32_t nof_prb,
ra_mcs_t *mcs); ra_mcs_t *mcs);
LIBLTE_API int ra_tbs_from_idx_format1c(uint32_t tbs_idx); LIBLTE_API int ra_tbs_from_idx_format1c(uint32_t tbs_idx);
LIBLTE_API int ra_tbs_to_table_idx_format1c(uint32_t tbs);
LIBLTE_API int ra_tbs_from_idx(uint32_t tbs_idx, LIBLTE_API int ra_tbs_from_idx(uint32_t tbs_idx,
uint32_t n_prb); uint32_t n_prb);
LIBLTE_API int ra_tbs_to_table_idx(uint32_t tbs, LIBLTE_API int ra_tbs_to_table_idx(uint32_t tbs,
uint32_t n_prb); uint32_t n_prb);
LIBLTE_API uint32_t ra_mcs_to_table_idx(ra_mcs_t *mcs);
LIBLTE_API int ra_mcs_from_idx_dl(uint32_t idx,
ra_mcs_t *mcs);
LIBLTE_API int ra_mcs_from_idx_ul(uint32_t idx,
ra_mcs_t *mcs);
LIBLTE_API char *ra_mod_string(ra_mod_t mod);
LIBLTE_API uint32_t ra_type0_P(uint32_t nof_prb); LIBLTE_API uint32_t ra_type0_P(uint32_t nof_prb);
LIBLTE_API uint32_t ra_type2_to_riv(uint32_t L_crb, LIBLTE_API uint32_t ra_type2_to_riv(uint32_t L_crb,
@ -199,13 +183,6 @@ LIBLTE_API uint32_t ra_type2_ngap(uint32_t nof_prb,
LIBLTE_API uint32_t ra_type1_N_rb(uint32_t nof_prb); LIBLTE_API uint32_t ra_type1_N_rb(uint32_t nof_prb);
LIBLTE_API void ra_pdsch_set_mcs_index(ra_pdsch_t *ra,
uint32_t mcs_idx);
LIBLTE_API void ra_pdsch_set_mcs(ra_pdsch_t *ra,
ra_mod_t mod,
uint32_t tbs_idx);
LIBLTE_API void ra_pdsch_fprint(FILE *f, LIBLTE_API void ra_pdsch_fprint(FILE *f,
ra_pdsch_t *ra, ra_pdsch_t *ra,
uint32_t nof_prb); uint32_t nof_prb);

@ -76,6 +76,36 @@ int lte_cb_size(uint32_t index) {
} }
} }
char *lte_mod_string(lte_mod_t mod) {
switch (mod) {
case LTE_BPSK:
return "BPSK";
case LTE_QPSK:
return "QPSK";
case LTE_QAM16:
return "QAM16";
case LTE_QAM64:
return "QAM64";
default:
return "N/A";
}
}
uint32_t lte_mod_bits_x_symbol(lte_mod_t mod) {
switch (mod) {
case LTE_BPSK:
return 1;
case LTE_QPSK:
return 2;
case LTE_QAM16:
return 4;
case LTE_QAM64:
return 6;
default:
return 0;
}
}
/* /*
* Finds index of minimum K>=long_cb in Table 5.1.3-3 of 36.212 * Finds index of minimum K>=long_cb in Table 5.1.3-3 of 36.212
*/ */

@ -37,14 +37,14 @@ void demod_hard_init(demod_hard_t* q) {
bzero((void*) q, sizeof(demod_hard_t)); bzero((void*) q, sizeof(demod_hard_t));
} }
void demod_hard_table_set(demod_hard_t* q, enum modem_std table) { void demod_hard_table_set(demod_hard_t* q, lte_mod_t mod) {
q->table = table; q->mod = mod;
} }
int demod_hard_demodulate(demod_hard_t* q, cf_t* symbols, char *bits, int nsymbols) { int demod_hard_demodulate(demod_hard_t* q, cf_t* symbols, char *bits, uint32_t nsymbols) {
int nbits=-1; int nbits=-1;
switch(q->table) { switch(q->mod) {
case LTE_BPSK: case LTE_BPSK:
hard_bpsk_demod(symbols,bits,nsymbols); hard_bpsk_demod(symbols,bits,nsymbols);
nbits=nsymbols; nbits=nsymbols;

@ -69,7 +69,7 @@ int demod_soft_demodulate(demod_soft_t *q, const cf_t* symbols, float* llr, int
/* High-Level API */ /* High-Level API */
int demod_soft_initialize(demod_soft_hl* hl) { int demod_soft_initialize(demod_soft_hl* hl) {
modem_table_init(&hl->table); modem_table_init(&hl->table);
if (modem_table_std(&hl->table,hl->init.std,true)) { if (modem_table_lte(&hl->table,hl->init.std,true)) {
return -1; return -1;
} }
demod_soft_init(&hl->obj); demod_soft_init(&hl->obj);

@ -33,6 +33,7 @@
#include "liblte/phy/modem/demod_hard.h" #include "liblte/phy/modem/demod_hard.h"
#include "hard_demod_lte.h" #include "hard_demod_lte.h"
/** /**
* @ingroup Hard BPSK demodulator * @ingroup Hard BPSK demodulator
* *
@ -46,9 +47,9 @@
* \param N Number of input symbols * \param N Number of input symbols
* \param modulation Modulation type * \param modulation Modulation type
*/ */
inline void hard_bpsk_demod(const cf_t* in, char* out, int N) inline void hard_bpsk_demod(const cf_t* in, char* out, uint32_t N)
{ {
int s; uint32_t s;
for (s=0; s<N; s++) { /* received symbols */ for (s=0; s<N; s++) { /* received symbols */
if (__real__ in[s] > 0) { if (__real__ in[s] > 0) {
@ -81,9 +82,9 @@ inline void hard_bpsk_demod(const cf_t* in, char* out, int N)
* \param N Number of input symbols * \param N Number of input symbols
* \param modulation Modulation type * \param modulation Modulation type
*/ */
inline void hard_qpsk_demod(const cf_t* in, char* out, int N) inline void hard_qpsk_demod(const cf_t* in, char* out, uint32_t N)
{ {
int s; uint32_t s;
for (s=0; s<N; s++) { for (s=0; s<N; s++) {
if (__real__ in[s] > 0) { if (__real__ in[s] > 0) {
@ -115,9 +116,9 @@ inline void hard_qpsk_demod(const cf_t* in, char* out, int N)
* \param N Number of input symbols * \param N Number of input symbols
* \param modulation Modulation type * \param modulation Modulation type
*/ */
inline void hard_qam16_demod(const cf_t* in, char* out, int N) inline void hard_qam16_demod(const cf_t* in, char* out, uint32_t N)
{ {
int s; uint32_t s;
for (s=0; s<N; s++) { for (s=0; s<N; s++) {
if (__real__ in[s] > 0) { if (__real__ in[s] > 0) {
@ -157,9 +158,9 @@ inline void hard_qam16_demod(const cf_t* in, char* out, int N)
* \param N Number of input symbols * \param N Number of input symbols
* \param modulation Modulation type * \param modulation Modulation type
*/ */
inline void hard_qam64_demod(const cf_t* in, char* out, int N) inline void hard_qam64_demod(const cf_t* in, char* out, uint32_t N)
{ {
int s; uint32_t s;
for (s=0; s<N; s++) { for (s=0; s<N; s++) {
/* bits associated with/obtained from in-phase component: b0, b2, b4 */ /* bits associated with/obtained from in-phase component: b0, b2, b4 */

@ -25,7 +25,6 @@
* *
*/ */
/* Thresholds for Demodulation */ /* Thresholds for Demodulation */
/* Assume perfect amplitude and phase alignment. /* Assume perfect amplitude and phase alignment.
* Check threshold values for real case * Check threshold values for real case
@ -35,7 +34,18 @@
#define QAM64_THRESHOLD_2 4/sqrt(42) #define QAM64_THRESHOLD_2 4/sqrt(42)
#define QAM64_THRESHOLD_3 6/sqrt(42) #define QAM64_THRESHOLD_3 6/sqrt(42)
void hard_bpsk_demod(const cf_t* in, char* out, int N); void hard_bpsk_demod(const cf_t* in,
void hard_qpsk_demod(const cf_t* in, char* out, int N); char* out,
void hard_qam16_demod(const cf_t* in, char* out, int N); uint32_t N);
void hard_qam64_demod(const cf_t* in, char* out, int N);
void hard_qpsk_demod(const cf_t* in,
char* out,
uint32_t N);
void hard_qam16_demod(const cf_t* in,
char* out,
uint32_t N);
void hard_qam64_demod(const cf_t* in,
char* out,
uint32_t N);

@ -59,7 +59,7 @@ void set_BPSKtable(cf_t* table, soft_table_t *soft_table, bool compute_soft_demo
* Set the QPSK modulation table */ * Set the QPSK modulation table */
void set_QPSKtable(cf_t* table, soft_table_t *soft_table, bool compute_soft_demod) void set_QPSKtable(cf_t* table, soft_table_t *soft_table, bool compute_soft_demod)
{ {
int i,j; uint32_t i,j;
// LTE-QPSK constellation: // LTE-QPSK constellation:
// Q // Q
@ -97,7 +97,7 @@ void set_QPSKtable(cf_t* table, soft_table_t *soft_table, bool compute_soft_demo
* Set the 16QAM modulation table */ * Set the 16QAM modulation table */
void set_16QAMtable(cf_t* table, soft_table_t *soft_table, bool compute_soft_demod) void set_16QAMtable(cf_t* table, soft_table_t *soft_table, bool compute_soft_demod)
{ {
int i,j; uint32_t i,j;
// LTE-16QAM constellation: // LTE-16QAM constellation:
// Q // Q
// 1011 1001 | 0001 0011 // 1011 1001 | 0001 0011
@ -162,7 +162,7 @@ void set_16QAMtable(cf_t* table, soft_table_t *soft_table, bool compute_soft_dem
* Set the 64QAM modulation table */ * Set the 64QAM modulation table */
void set_64QAMtable(cf_t* table, soft_table_t *soft_table, bool compute_soft_demod) void set_64QAMtable(cf_t* table, soft_table_t *soft_table, bool compute_soft_demod)
{ {
int i,j; uint32_t i,j;
// LTE-64QAM constellation: // LTE-64QAM constellation:
// see [3GPP TS 36.211 version 10.5.0 Release 10, Section 7.1.4] // see [3GPP TS 36.211 version 10.5.0 Release 10, Section 7.1.4]
table[0] = QAM64_LEVEL_2 + QAM64_LEVEL_2*_Complex_I; table[0] = QAM64_LEVEL_2 + QAM64_LEVEL_2*_Complex_I;

@ -45,7 +45,18 @@
void set_BPSKtable(cf_t* table, soft_table_t *soft_table, bool compute_soft_demod); void set_BPSKtable(cf_t* table,
void set_QPSKtable(cf_t* table, soft_table_t *soft_table, bool compute_soft_demod); soft_table_t *soft_table,
void set_16QAMtable(cf_t* table, soft_table_t *soft_table, bool compute_soft_demod); bool compute_soft_demod);
void set_64QAMtable(cf_t* table, soft_table_t *soft_table, bool compute_soft_demod);
void set_QPSKtable(cf_t* table,
soft_table_t *soft_table,
bool compute_soft_demod);
void set_16QAMtable(cf_t* table,
soft_table_t *soft_table,
bool compute_soft_demod);
void set_64QAMtable(cf_t* table,
soft_table_t *soft_table,
bool compute_soft_demod);

@ -35,14 +35,17 @@
/** Low-level API */ /** Low-level API */
int mod_modulate(modem_table_t* q, const char *bits, cf_t* symbols, int nbits) { int mod_modulate(modem_table_t* q, const char *bits, cf_t* symbols, uint32_t nbits) {
int i,j,idx; uint32_t i,j,idx;
char *b_ptr=(char*) bits; char *b_ptr=(char*) bits;
j=0; j=0;
for (i=0;i<nbits;i+=q->nbits_x_symbol) { for (i=0;i<nbits;i+=q->nbits_x_symbol) {
idx = bit_unpack(&b_ptr,q->nbits_x_symbol); idx = bit_unpack(&b_ptr,q->nbits_x_symbol);
assert(idx >= 0 && idx < q->nsymbols); if (idx < q->nsymbols) {
symbols[j] = q->symbol_table[idx]; symbols[j] = q->symbol_table[idx];
} else {
return LIBLTE_ERROR;
}
j++; j++;
} }
return j; return j;
@ -52,7 +55,7 @@ int mod_modulate(modem_table_t* q, const char *bits, cf_t* symbols, int nbits) {
/* High-Level API */ /* High-Level API */
int mod_initialize(mod_hl* hl) { int mod_initialize(mod_hl* hl) {
modem_table_init(&hl->obj); modem_table_init(&hl->obj);
if (modem_table_std(&hl->obj,hl->init.std,false)) { if (modem_table_lte(&hl->obj,hl->init.std,false)) {
return -1; return -1;
} }

@ -33,6 +33,7 @@
#include <string.h> #include <string.h>
#include <strings.h> #include <strings.h>
#include "liblte/phy/common/phy_common.h"
#include "liblte/phy/modem/modem_table.h" #include "liblte/phy/modem/modem_table.h"
#include "lte_tables.h" #include "lte_tables.h"
@ -56,27 +57,27 @@ void modem_table_reset(modem_table_t* q) {
modem_table_init(q); modem_table_init(q);
} }
int modem_table_set(modem_table_t* q, cf_t* table, soft_table_t *soft_table, int nsymbols, int nbits_x_symbol) { int modem_table_set(modem_table_t* q, cf_t* table, soft_table_t *soft_table, uint32_t nsymbols, uint32_t nbits_x_symbol) {
if (q->nsymbols) { if (q->nsymbols) {
return -1; return LIBLTE_ERROR;
} }
q->nsymbols = nsymbols; q->nsymbols = nsymbols;
if (table_create(q)) { if (table_create(q)) {
return -1; return LIBLTE_ERROR;
} }
memcpy(q->symbol_table,table,q->nsymbols*sizeof(cf_t)); memcpy(q->symbol_table,table,q->nsymbols*sizeof(cf_t));
memcpy(&q->soft_table,soft_table,sizeof(soft_table_t)); memcpy(&q->soft_table,soft_table,sizeof(soft_table_t));
q->nbits_x_symbol = nbits_x_symbol; q->nbits_x_symbol = nbits_x_symbol;
return 0; return LIBLTE_SUCCESS;
} }
int modem_table_std(modem_table_t* q, enum modem_std std, bool compute_soft_demod) { int modem_table_lte(modem_table_t* q, lte_mod_t modulation, bool compute_soft_demod) {
switch(std) { switch(modulation) {
case LTE_BPSK: case LTE_BPSK:
q->nbits_x_symbol = 1; q->nbits_x_symbol = 1;
q->nsymbols = 2; q->nsymbols = 2;
if (table_create(q)) { if (table_create(q)) {
return -1; return LIBLTE_ERROR;
} }
set_BPSKtable(q->symbol_table, &q->soft_table, compute_soft_demod); set_BPSKtable(q->symbol_table, &q->soft_table, compute_soft_demod);
break; break;
@ -84,7 +85,7 @@ int modem_table_std(modem_table_t* q, enum modem_std std, bool compute_soft_dem
q->nbits_x_symbol = 2; q->nbits_x_symbol = 2;
q->nsymbols = 4; q->nsymbols = 4;
if (table_create(q)) { if (table_create(q)) {
return -1; return LIBLTE_ERROR;
} }
set_QPSKtable(q->symbol_table, &q->soft_table, compute_soft_demod); set_QPSKtable(q->symbol_table, &q->soft_table, compute_soft_demod);
break; break;
@ -92,7 +93,7 @@ int modem_table_std(modem_table_t* q, enum modem_std std, bool compute_soft_dem
q->nbits_x_symbol = 4; q->nbits_x_symbol = 4;
q->nsymbols = 16; q->nsymbols = 16;
if (table_create(q)) { if (table_create(q)) {
return -1; return LIBLTE_ERROR;
} }
set_16QAMtable(q->symbol_table, &q->soft_table, compute_soft_demod); set_16QAMtable(q->symbol_table, &q->soft_table, compute_soft_demod);
break; break;
@ -100,10 +101,10 @@ int modem_table_std(modem_table_t* q, enum modem_std std, bool compute_soft_dem
q->nbits_x_symbol = 6; q->nbits_x_symbol = 6;
q->nsymbols = 64; q->nsymbols = 64;
if (table_create(q)) { if (table_create(q)) {
return -1; return LIBLTE_ERROR;
} }
set_64QAMtable(q->symbol_table, &q->soft_table, compute_soft_demod); set_64QAMtable(q->symbol_table, &q->soft_table, compute_soft_demod);
break; break;
} }
return 0; return LIBLTE_SUCCESS;
} }

@ -51,7 +51,7 @@
* \param sigma2 Noise vatiance * \param sigma2 Noise vatiance
*/ */
void llr_approx(const _Complex float *in, float *out, int N, int M, int B, void llr_approx(const _Complex float *in, float *out, int N, int M, int B,
_Complex float *symbols, int (*S)[6][32], float sigma2) { _Complex float *symbols, uint32_t (*S)[6][32], float sigma2) {
int i, s, b; int i, s, b;
float num, den; float num, den;
float new_num, new_den; float new_num, new_den;
@ -112,7 +112,7 @@ void llr_approx(const _Complex float *in, float *out, int N, int M, int B,
* \param sigma2 Noise vatiance * \param sigma2 Noise vatiance
*/ */
void llr_exact(const _Complex float *in, float *out, int N, int M, int B, void llr_exact(const _Complex float *in, float *out, int N, int M, int B,
_Complex float *symbols, int (*S)[6][32], float sigma2) { _Complex float *symbols, uint32_t (*S)[6][32], float sigma2) {
int i, s, b; int i, s, b;
float num, den; float num, den;
float idiff0, qdiff0, idiff1, qdiff1; float idiff0, qdiff0, idiff1, qdiff1;

@ -26,8 +26,20 @@
*/ */
void llr_approx(const _Complex float *in, float *out, int N, int M, int B, void llr_approx(const _Complex float *in,
_Complex float *symbols, int (*S)[6][32], float sigma2); float *out,
int N,
int M,
int B,
_Complex float *symbols,
uint32_t (*S)[6][32],
float sigma2);
void llr_exact(const _Complex float *in, float *out, int N, int M, int B, void llr_exact(const _Complex float *in,
_Complex float *symbols, int (*S)[6][32], float sigma2); float *out,
int N,
int M,
int B,
_Complex float *symbols,
uint32_t (*S)[6][32],
float sigma2);

@ -37,7 +37,7 @@
#include "liblte/phy/phy.h" #include "liblte/phy/phy.h"
int num_bits = 1000; int num_bits = 1000;
enum modem_std modulation; lte_mod_t modulation;
bool soft_output = false, soft_exact = false; bool soft_output = false, soft_exact = false;
void usage(char *prog) { void usage(char *prog) {
@ -101,7 +101,7 @@ int main(int argc, char **argv) {
parse_args(argc, argv); parse_args(argc, argv);
/* initialize objects */ /* initialize objects */
if (modem_table_std(&mod, modulation, soft_output)) { if (modem_table_lte(&mod, modulation, soft_output)) {
fprintf(stderr, "Error initializing modem table\n"); fprintf(stderr, "Error initializing modem table\n");
exit(-1); exit(-1);
} }

@ -41,6 +41,54 @@
#include "liblte/phy/utils/debug.h" #include "liblte/phy/utils/debug.h"
int dci_msg_to_ra_dl(dci_msg_t *msg, uint16_t msg_rnti, uint16_t c_rnti,
lte_cell_t cell, uint32_t cfi,
ra_pdsch_t *ra_dl)
{
int ret = LIBLTE_ERROR_INVALID_INPUTS;
if (msg != NULL &&
ra_dl != NULL &&
lte_cell_isvalid(&cell) &&
cfi > 0 &&
cfi < 4)
{
ret = LIBLTE_ERROR;
dci_msg_type_t type;
if (dci_msg_get_type(msg, &type, cell.nof_prb, msg_rnti, c_rnti)) {
fprintf(stderr, "Can't get DCI message type\n");
return ret;
}
if (VERBOSE_ISINFO()) {
dci_msg_type_fprint(stdout, type);
}
if (type.type == PDSCH_SCHED) {
bzero(ra_dl, sizeof(ra_pdsch_t));
if (dci_msg_unpack_pdsch(msg, ra_dl, cell.nof_prb, msg_rnti != SIRNTI)) {
fprintf(stderr, "Can't unpack PDSCH message\n");
return ret;
}
if (VERBOSE_ISINFO()) {
ra_pdsch_fprint(stdout, ra_dl, cell.nof_prb);
}
if (ra_prb_get_dl(&ra_dl->prb_alloc, ra_dl, cell.nof_prb)) {
fprintf(stderr, "Error computing resource allocation\n");
return ret;
}
ra_prb_get_re_dl(&ra_dl->prb_alloc, cell.nof_prb, cell.nof_ports, cell.nof_prb<10?(cfi+1):cfi, cell.cp);
ret = LIBLTE_SUCCESS;
}
}
return ret;
}
int dci_location_set(dci_location_t *c, uint32_t L, uint32_t nCCE) { int dci_location_set(dci_location_t *c, uint32_t L, uint32_t nCCE) {
if (L <= 3) { if (L <= 3) {
c->L = L; c->L = L;
@ -186,31 +234,10 @@ int dci_format0_pack(ra_pusch_t *data, dci_msg_t *msg, uint32_t nof_prb) {
} else { } else {
riv = data->type2_alloc.riv; riv = data->type2_alloc.riv;
} }
bit_pack((uint32_t) riv, &y, riv_nbits(nof_prb) - n_ul_hop); bit_pack(riv, &y, riv_nbits(nof_prb) - n_ul_hop);
/* pack MCS according to 8.6.1 of 36.213 */ /* pack MCS according to 8.6.1 of 36.213 */
uint32_t mcs; bit_pack(data->mcs_idx, &y, 5);
if (data->cqi_request) {
mcs = 29;
} else {
if (data->rv_idx) {
mcs = 28 + data->rv_idx;
} else {
if (data->mcs.mod == MOD_NULL) {
mcs = data->mcs.mcs_idx;
} else {
if (data->mcs.tbs) {
if (data->mcs.tbs) {
data->mcs.tbs_idx = ra_tbs_to_table_idx(data->mcs.tbs,
ra_nprb_ul(data, nof_prb));
}
}
mcs = ra_mcs_to_table_idx(&data->mcs);
}
}
}
bit_pack((uint32_t) mcs, &y, 5);
*y++ = data->ndi; *y++ = data->ndi;
@ -276,7 +303,7 @@ int dci_format0_unpack(dci_msg_t *msg, ra_pusch_t *data, uint32_t nof_prb) {
data->type2_alloc.riv = riv; data->type2_alloc.riv = riv;
/* unpack MCS according to 8.6 of 36.213 */ /* unpack MCS according to 8.6 of 36.213 */
uint32_t mcs = bit_unpack(&y, 5); data->mcs_idx = bit_unpack(&y, 5);
data->ndi = *y++ ? true : false; data->ndi = *y++ ? true : false;
@ -287,20 +314,16 @@ int dci_format0_unpack(dci_msg_t *msg, ra_pusch_t *data, uint32_t nof_prb) {
data->cqi_request = *y++ ? true : false; data->cqi_request = *y++ ? true : false;
// 8.6.2 First paragraph // 8.6.2 First paragraph
if (mcs <= 28) { if (data->mcs_idx <= 28) {
ra_mcs_from_idx_ul(mcs, &data->mcs); ra_mcs_from_idx_ul(data->mcs_idx, ra_nprb_ul(data, nof_prb), &data->mcs);
data->mcs.tbs = ra_tbs_from_idx(data->mcs.tbs_idx, } else if (data->mcs_idx == 29 && data->cqi_request && ra_nprb_ul(data, nof_prb) <= 4) {
ra_nprb_ul(data, nof_prb));
}
// 8.6.1 and 8.6.2 36.213 second paragraph // 8.6.1 and 8.6.2 36.213 second paragraph
if (mcs == 29 && data->cqi_request && ra_nprb_ul(data, nof_prb) <= 4) { data->mcs.mod = LTE_QPSK;
data->mcs.mod = QPSK; data->mcs.tbs = 0;
} } else if (data->mcs_idx >= 29) {
if (mcs > 29) { // Else leave TBS and use the previously used PUSCH modulation
// Else leave MOD_NULL and use the previously used PUSCH modulation data->mcs.tbs = 0;
data->mcs.mod = MOD_NULL; data->rv_idx = data->mcs_idx - 28;
data->rv_idx = mcs - 28;
} }
return LIBLTE_SUCCESS; return LIBLTE_SUCCESS;
@ -340,27 +363,16 @@ int dci_format1_pack(ra_pdsch_t *data, dci_msg_t *msg, uint32_t nof_prb) {
return LIBLTE_ERROR; return LIBLTE_ERROR;
} }
/* pack MCS according to 7.1.7 of 36.213 */ /* pack MCS */
uint32_t mcs; bit_pack(data->mcs_idx, &y, 5);
if (data->mcs.mod == MOD_NULL) {
mcs = data->mcs.mcs_idx;
} else {
if (data->mcs.tbs) {
data->mcs.tbs_idx = ra_tbs_to_table_idx(data->mcs.tbs,
ra_nprb_dl(data, nof_prb));
}
mcs = ra_mcs_to_table_idx(&data->mcs);
data->mcs.mcs_idx = mcs;
}
bit_pack((uint32_t) mcs, &y, 5);
/* harq process number */ /* harq process number */
bit_pack((uint32_t) data->harq_process, &y, 3); bit_pack(data->harq_process, &y, 3);
*y++ = data->ndi; *y++ = data->ndi;
// rv version // rv version
bit_pack((uint32_t) data->rv_idx, &y, 2); bit_pack(data->rv_idx, &y, 2);
// TPC not implemented // TPC not implemented
*y++ = 0; *y++ = 0;
@ -412,20 +424,12 @@ int dci_format1_unpack(dci_msg_t *msg, ra_pdsch_t *data, uint32_t nof_prb) {
} }
/* unpack MCS according to 7.1.7 of 36.213 */ /* unpack MCS according to 7.1.7 of 36.213 */
uint32_t mcs = bit_unpack(&y, 5); data->mcs_idx = bit_unpack(&y, 5);
data->mcs.mcs_idx = mcs; if (ra_mcs_from_idx_dl(data->mcs_idx, ra_nprb_dl(data, nof_prb), &data->mcs)) {
if (ra_mcs_from_idx_dl(mcs, &data->mcs)) {
fprintf(stderr, "Error getting MCS\n"); fprintf(stderr, "Error getting MCS\n");
return LIBLTE_ERROR; return LIBLTE_ERROR;
} }
int t = ra_tbs_from_idx(data->mcs.tbs_idx, ra_nprb_dl(data, nof_prb));
if (t < 0) {
fprintf(stderr, "Error getting TBS\n");
return LIBLTE_ERROR;
}
data->mcs.tbs = (uint32_t) t;
/* harq process number */ /* harq process number */
data->harq_process = bit_unpack(&y, 3); data->harq_process = bit_unpack(&y, 3);
@ -491,28 +495,12 @@ int dci_format1As_pack(ra_pdsch_t *data, dci_msg_t *msg, uint32_t nof_prb,
nb_gap = 1; nb_gap = 1;
*y++ = data->type2_alloc.n_gap; *y++ = data->type2_alloc.n_gap;
} }
bit_pack((uint32_t) riv, &y, riv_nbits(nof_prb) - nb_gap); bit_pack(riv, &y, riv_nbits(nof_prb) - nb_gap);
// in format1A, MCS = TBS according to 7.1.7.2 of 36.213 // in format1A, MCS = TBS according to 7.1.7.2 of 36.213
uint32_t mcs; bit_pack(data->mcs_idx, &y, 5);
if (data->mcs.mod == MOD_NULL) {
mcs = data->mcs.mcs_idx;
} else {
if (data->mcs.tbs) {
// In format 1A, n_prb_1a is 2 or 3 if crc is not scrambled with C-RNTI
uint32_t n_prb;
if (!crc_is_crnti) {
n_prb = ra_nprb_dl(data, nof_prb);
} else {
n_prb = data->type2_alloc.n_prb1a == nprb1a_2 ? 2 : 3;
}
data->mcs.tbs_idx = ra_tbs_to_table_idx(data->mcs.tbs, n_prb);
}
mcs = data->mcs.tbs_idx;
}
bit_pack((uint32_t) mcs, &y, 5);
bit_pack((uint32_t) data->harq_process, &y, 3); bit_pack(data->harq_process, &y, 3);
if (!crc_is_crnti && nof_prb >= 50 && data->type2_alloc.mode == t2_dist) { if (!crc_is_crnti && nof_prb >= 50 && data->type2_alloc.mode == t2_dist) {
*y++ = data->type2_alloc.n_gap; *y++ = data->type2_alloc.n_gap;
@ -521,7 +509,7 @@ int dci_format1As_pack(ra_pdsch_t *data, dci_msg_t *msg, uint32_t nof_prb,
} }
// rv version // rv version
bit_pack((uint32_t) data->rv_idx, &y, 2); bit_pack(data->rv_idx, &y, 2);
if (crc_is_crnti) { if (crc_is_crnti) {
// TPC not implemented // TPC not implemented
@ -586,7 +574,7 @@ int dci_format1As_unpack(dci_msg_t *msg, ra_pdsch_t *data, uint32_t nof_prb,
data->type2_alloc.riv = riv; data->type2_alloc.riv = riv;
// unpack MCS // unpack MCS
data->mcs.mcs_idx = bit_unpack(&y, 5); data->mcs_idx = bit_unpack(&y, 5);
data->harq_process = bit_unpack(&y, 3); data->harq_process = bit_unpack(&y, 3);
@ -597,7 +585,7 @@ int dci_format1As_unpack(dci_msg_t *msg, ra_pdsch_t *data, uint32_t nof_prb,
} }
// rv version // rv version
bit_pack((uint32_t) data->rv_idx, &y, 2); bit_pack(data->rv_idx, &y, 2);
if (crc_is_crnti) { if (crc_is_crnti) {
// TPC not implemented // TPC not implemented
@ -607,7 +595,6 @@ int dci_format1As_unpack(dci_msg_t *msg, ra_pdsch_t *data, uint32_t nof_prb,
y++; // MSB of TPC is reserved y++; // MSB of TPC is reserved
data->type2_alloc.n_prb1a = *y++; // LSB indicates N_prb_1a for TBS data->type2_alloc.n_prb1a = *y++; // LSB indicates N_prb_1a for TBS
} }
data->mcs.tbs_idx = data->mcs.mcs_idx;
uint32_t n_prb; uint32_t n_prb;
if (crc_is_crnti) { if (crc_is_crnti) {
@ -615,8 +602,8 @@ int dci_format1As_unpack(dci_msg_t *msg, ra_pdsch_t *data, uint32_t nof_prb,
} else { } else {
n_prb = data->type2_alloc.n_prb1a == nprb1a_2 ? 2 : 3; n_prb = data->type2_alloc.n_prb1a == nprb1a_2 ? 2 : 3;
} }
data->mcs.tbs = ra_tbs_from_idx(data->mcs.tbs_idx, n_prb); data->mcs.tbs = ra_tbs_from_idx(data->mcs_idx, n_prb);
data->mcs.mod = QPSK; data->mcs.mod = LTE_QPSK;
return LIBLTE_SUCCESS; return LIBLTE_SUCCESS;
} }
@ -664,19 +651,10 @@ int dci_format1Cs_pack(ra_pdsch_t *data, dci_msg_t *msg, uint32_t nof_prb) {
} else { } else {
riv = data->type2_alloc.riv; riv = data->type2_alloc.riv;
} }
bit_pack((uint32_t) riv, &y, riv_nbits((int) n_vrb_dl / n_step)); bit_pack(riv, &y, riv_nbits((int) n_vrb_dl / n_step));
// in format1C, MCS = TBS according to 7.1.7.2 of 36.213 // in format1C, MCS = TBS according to 7.1.7.2 of 36.213
uint32_t mcs; bit_pack(data->mcs_idx, &y, 5);
if (data->mcs.mod == MOD_NULL) {
mcs = data->mcs.mcs_idx;
} else {
if (data->mcs.tbs) {
data->mcs.tbs_idx = ra_tbs_to_table_idx_format1c(data->mcs.tbs);
}
mcs = data->mcs.tbs_idx;
}
bit_pack((uint32_t) mcs, &y, 5);
msg->nof_bits = (y - msg->data); msg->nof_bits = (y - msg->data);
@ -709,10 +687,9 @@ int dci_format1Cs_unpack(dci_msg_t *msg, ra_pdsch_t *data, uint32_t nof_prb) {
data->type2_alloc.RB_start = RB_p * n_step; data->type2_alloc.RB_start = RB_p * n_step;
data->type2_alloc.riv = riv; data->type2_alloc.riv = riv;
data->mcs.mcs_idx = bit_unpack(&y, 5); data->mcs_idx = bit_unpack(&y, 5);
data->mcs.tbs_idx = data->mcs.mcs_idx; data->mcs.tbs = ra_tbs_from_idx_format1c(data->mcs_idx);
data->mcs.tbs = ra_tbs_from_idx_format1c(data->mcs.tbs_idx); data->mcs.mod = LTE_QPSK;
data->mcs.mod = QPSK;
msg->nof_bits = (y - msg->data); msg->nof_bits = (y - msg->data);

@ -134,7 +134,7 @@ int pbch_init(pbch_t *q, lte_cell_t cell) {
bzero(q, sizeof(pbch_t)); bzero(q, sizeof(pbch_t));
q->cell = cell; q->cell = cell;
if (modem_table_std(&q->mod, LTE_QPSK, true)) { if (modem_table_lte(&q->mod, LTE_QPSK, true)) {
goto clean; goto clean;
} }
demod_soft_init(&q->demod); demod_soft_init(&q->demod);

@ -70,7 +70,7 @@ int pcfich_init(pcfich_t *q, regs_t *regs, lte_cell_t cell) {
q->cell = cell; q->cell = cell;
q->regs = regs; q->regs = regs;
if (modem_table_std(&q->mod, LTE_QPSK, false)) { if (modem_table_lte(&q->mod, LTE_QPSK, false)) {
goto clean; goto clean;
} }

@ -77,7 +77,7 @@ int pdcch_init(pdcch_t *q, regs_t *regs, lte_cell_t cell) {
INFO("Init PDCCH: %d bits, %d symbols, %d ports\n", q->max_bits, q->max_bits/2, q->cell.nof_ports); INFO("Init PDCCH: %d bits, %d symbols, %d ports\n", q->max_bits, q->max_bits/2, q->cell.nof_ports);
if (modem_table_std(&q->mod, LTE_QPSK, true)) { if (modem_table_lte(&q->mod, LTE_QPSK, true)) {
goto clean; goto clean;
} }
if (crc_init(&q->crc, LTE_CRC16, 16)) { if (crc_init(&q->crc, LTE_CRC16, 16)) {
@ -89,7 +89,9 @@ int pdcch_init(pdcch_t *q, regs_t *regs, lte_cell_t cell) {
demod_soft_alg_set(&q->demod, APPROX); demod_soft_alg_set(&q->demod, APPROX);
for (i = 0; i < NSUBFRAMES_X_FRAME; i++) { for (i = 0; i < NSUBFRAMES_X_FRAME; i++) {
if (sequence_pdcch(&q->seq_pdcch[i], 2 * i, q->cell.id, q->max_bits)) { // we need to pregenerate the sequence for the maximum number of bits, which is 8 times
// the maximum number of REGs (for CFI=3)
if (sequence_pdcch(&q->seq_pdcch[i], 2 * i, q->cell.id, 8*regs_pdcch_nregs(q->regs, 3))) {
goto clean; goto clean;
} }
} }
@ -178,7 +180,8 @@ void pdcch_free(pdcch_t *q) {
uint32_t pdcch_ue_locations(pdcch_t *q, dci_location_t *c, uint32_t max_candidates, uint32_t pdcch_ue_locations(pdcch_t *q, dci_location_t *c, uint32_t max_candidates,
uint32_t nsubframe, uint32_t cfi, uint16_t rnti) { uint32_t nsubframe, uint32_t cfi, uint16_t rnti) {
uint32_t i, k, l, L, m; int l; // this must be int because of the for(;;--) loop
uint32_t i, k, L, m;
uint32_t Yk, ncce; uint32_t Yk, ncce;
const int S[4] = { 6, 12, 8, 16 }; const int S[4] = { 6, 12, 8, 16 };
@ -198,7 +201,7 @@ uint32_t pdcch_ue_locations(pdcch_t *q, dci_location_t *c, uint32_t max_candidat
for (i = 0; i < MIN(q->nof_cce / L, 16 / S[l]); i++) { for (i = 0; i < MIN(q->nof_cce / L, 16 / S[l]); i++) {
ncce = L * ((Yk + i) % (q->nof_cce / L)); ncce = L * ((Yk + i) % (q->nof_cce / L));
if (k < max_candidates && if (k < max_candidates &&
ncce + PDCCH_FORMAT_NOF_CCE(L) < q->nof_cce) ncce + PDCCH_FORMAT_NOF_CCE(l) <= q->nof_cce)
{ {
c[k].L = l; c[k].L = l;
c[k].ncce = ncce; c[k].ncce = ncce;
@ -352,8 +355,8 @@ int pdcch_extract_llr(pdcch_t *q, cf_t *sf_symbols, cf_t *ce[MAX_PORTS],
if (location.ncce + PDCCH_FORMAT_NOF_CCE(location.L) <= q->nof_cce) { if (location.ncce + PDCCH_FORMAT_NOF_CCE(location.L) <= q->nof_cce) {
INFO("Extracting LLRs: E: %d, nCCE: %d, L: %d\n", INFO("Extracting LLRs: E: %d, nCCE: %d, L: %d, SF: %d, CFI: %d\n",
q->e_bits, location.ncce, location.L); q->e_bits, location.ncce, location.L, nsubframe, cfi);
/* number of layers equals number of ports */ /* number of layers equals number of ports */
for (i = 0; i < q->cell.nof_ports; i++) { for (i = 0; i < q->cell.nof_ports; i++) {

@ -46,7 +46,7 @@
const enum modem_std modulations[4] = const lte_mod_t modulations[4] =
{ LTE_BPSK, LTE_QPSK, LTE_QAM16, LTE_QAM64 }; { LTE_BPSK, LTE_QPSK, LTE_QAM16, LTE_QAM64 };
@ -191,7 +191,7 @@ int pdsch_init(pdsch_t *q, uint16_t user_rnti, lte_cell_t cell) {
q->cell.nof_prb, q->max_symbols); q->cell.nof_prb, q->max_symbols);
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
if (modem_table_std(&q->mod[i], modulations[i], true)) { if (modem_table_lte(&q->mod[i], modulations[i], true)) {
goto clean; goto clean;
} }
} }
@ -220,12 +220,12 @@ int pdsch_init(pdsch_t *q, uint16_t user_rnti, lte_cell_t cell) {
} }
// Allocate floats for reception (LLRs) // Allocate floats for reception (LLRs)
q->cb_in = malloc(sizeof(float) * MAX_LONG_CB); q->cb_in = malloc(sizeof(char) * MAX_LONG_CB);
if (!q->cb_in) { if (!q->cb_in) {
goto clean; goto clean;
} }
q->cb_out = malloc(sizeof(char) * (3 * MAX_LONG_CB + 12)); q->cb_out = malloc(sizeof(float) * (3 * MAX_LONG_CB + 12));
if (!q->cb_out) { if (!q->cb_out) {
goto clean; goto clean;
} }
@ -417,8 +417,7 @@ int pdsch_harq_setup(pdsch_harq_t *p, ra_mcs_t mcs, ra_prb_t *prb_alloc) {
int ret = LIBLTE_ERROR_INVALID_INPUTS; int ret = LIBLTE_ERROR_INVALID_INPUTS;
if (p != NULL && if (p != NULL &&
mcs.tbs > 0 && mcs.tbs > 0)
mcs.mod != MOD_NULL)
{ {
uint32_t nof_bits, nof_bits_e, nof_symbols; uint32_t nof_bits, nof_bits_e, nof_symbols;
@ -429,7 +428,7 @@ int pdsch_harq_setup(pdsch_harq_t *p, ra_mcs_t mcs, ra_prb_t *prb_alloc) {
nof_bits = mcs.tbs; nof_bits = mcs.tbs;
nof_symbols = prb_alloc->re_sf[1]; // Any subframe except 0 and 5 has maximum RE nof_symbols = prb_alloc->re_sf[1]; // Any subframe except 0 and 5 has maximum RE
nof_bits_e = nof_symbols * ra_mod_bits_x_symbol(mcs.mod); nof_bits_e = nof_symbols * lte_mod_bits_x_symbol(mcs.mod);
if (nof_bits > nof_bits_e) { if (nof_bits > nof_bits_e) {
fprintf(stderr, "Invalid code rate %.2f\n", (float) nof_bits / nof_bits_e); fprintf(stderr, "Invalid code rate %.2f\n", (float) nof_bits / nof_bits_e);
@ -506,18 +505,18 @@ int pdsch_decode_tb(pdsch_t *q, char *data, uint32_t tbs, uint32_t nb_e,
/* Rate Unmatching */ /* Rate Unmatching */
if (rm_turbo_rx(harq_process->pdsch_w_buff_f[i], harq_process->w_buff_size, if (rm_turbo_rx(harq_process->pdsch_w_buff_f[i], harq_process->w_buff_size,
&e_bits[rp], n_e, &e_bits[rp], n_e,
(float*) q->cb_in, 3 * cb_len + 12, rv_idx)) { (float*) q->cb_out, 3 * cb_len + 12, rv_idx)) {
fprintf(stderr, "Error in rate matching\n"); fprintf(stderr, "Error in rate matching\n");
return LIBLTE_ERROR; return LIBLTE_ERROR;
} }
/* Turbo Decoding */ /* Turbo Decoding */
tdec_run_all(&q->decoder, (float*) q->cb_in, q->cb_out, TDEC_ITERATIONS, tdec_run_all(&q->decoder, (float*) q->cb_out, q->cb_in, TDEC_ITERATIONS,
cb_len); cb_len);
if (harq_process->cb_segm.C > 1) { if (harq_process->cb_segm.C > 1) {
/* Check Codeblock CRC and stop early if incorrect */ /* Check Codeblock CRC and stop early if incorrect */
if (crc_checksum(&q->crc_cb, q->cb_out, cb_len)) { if (crc_checksum(&q->crc_cb, q->cb_in, cb_len)) {
INFO("Error in CB#%d\n",i); INFO("Error in CB#%d\n",i);
return LIBLTE_ERROR; return LIBLTE_ERROR;
} }
@ -525,13 +524,13 @@ int pdsch_decode_tb(pdsch_t *q, char *data, uint32_t tbs, uint32_t nb_e,
/* Copy data to another buffer, removing the Codeblock CRC */ /* Copy data to another buffer, removing the Codeblock CRC */
if (i < harq_process->cb_segm.C - 1) { if (i < harq_process->cb_segm.C - 1) {
memcpy(&data[wp], &q->cb_out[F], (rlen - F) * sizeof(char)); memcpy(&data[wp], &q->cb_in[F], (rlen - F) * sizeof(char));
} else { } else {
INFO("Last CB, appending parity: %d to %d from %d and 24 from %d\n", INFO("Last CB, appending parity: %d to %d from %d and 24 from %d\n",
rlen - F - 24, wp, F, rlen - 24); rlen - F - 24, wp, F, rlen - 24);
/* Append Transport Block parity bits to the last CB */ /* Append Transport Block parity bits to the last CB */
memcpy(&data[wp], &q->cb_out[F], (rlen - F - 24) * sizeof(char)); memcpy(&data[wp], &q->cb_in[F], (rlen - F - 24) * sizeof(char));
memcpy(parity, &q->cb_out[rlen - 24], 24 * sizeof(char)); memcpy(parity, &q->cb_in[rlen - 24], 24 * sizeof(char));
} }
/* Set read/write pointers */ /* Set read/write pointers */
@ -552,8 +551,10 @@ int pdsch_decode_tb(pdsch_t *q, char *data, uint32_t tbs, uint32_t nb_e,
} }
if (par_rx == par_tx) { if (par_rx == par_tx) {
INFO("TB decoded OK\n",i);
return LIBLTE_SUCCESS; return LIBLTE_SUCCESS;
} else { } else {
INFO("Error in TB parity\n",i);
return LIBLTE_ERROR; return LIBLTE_ERROR;
} }
} else { } else {
@ -649,7 +650,6 @@ int pdsch_encode_tb(pdsch_t *q, char *data, uint32_t tbs, uint32_t nb_e,
uint32_t par; uint32_t par;
uint32_t i; uint32_t i;
uint32_t cb_len, rp, wp, rlen, F, n_e; uint32_t cb_len, rp, wp, rlen, F, n_e;
char *cb_in = q->cb_in;
char *e_bits = q->pdsch_e; char *e_bits = q->pdsch_e;
if (q != NULL && if (q != NULL &&
@ -673,7 +673,7 @@ int pdsch_encode_tb(pdsch_t *q, char *data, uint32_t tbs, uint32_t nb_e,
/* Add filler bits to the new data buffer */ /* Add filler bits to the new data buffer */
for (i = 0; i < harq_process->cb_segm.F; i++) { for (i = 0; i < harq_process->cb_segm.F; i++) {
cb_in[i] = LTE_NULL_BIT; q->cb_in[i] = LTE_NULL_BIT;
} }
} }
@ -710,29 +710,29 @@ int pdsch_encode_tb(pdsch_t *q, char *data, uint32_t tbs, uint32_t nb_e,
if (rv_idx == 0) { if (rv_idx == 0) {
/* Copy data to another buffer, making space for the Codeblock CRC */ /* Copy data to another buffer, making space for the Codeblock CRC */
if (i < harq_process->cb_segm.C - 1) { if (i < harq_process->cb_segm.C - 1) {
memcpy(&cb_in[F], &data[rp], (rlen - F) * sizeof(char)); memcpy(&q->cb_in[F], &data[rp], (rlen - F) * sizeof(char));
} else { } else {
INFO("Last CB, appending parity: %d from %d and 24 to %d\n", INFO("Last CB, appending parity: %d from %d and 24 to %d\n",
rlen - F - 24, rp, rlen - 24); rlen - F - 24, rp, rlen - 24);
/* Append Transport Block parity bits to the last CB */ /* Append Transport Block parity bits to the last CB */
memcpy(&cb_in[F], &data[rp], (rlen - F - 24) * sizeof(char)); memcpy(&q->cb_in[F], &data[rp], (rlen - F - 24) * sizeof(char));
memcpy(&cb_in[rlen - 24], parity, 24 * sizeof(char)); memcpy(&q->cb_in[rlen - 24], parity, 24 * sizeof(char));
} }
if (harq_process->cb_segm.C > 1) { if (harq_process->cb_segm.C > 1) {
/* Attach Codeblock CRC */ /* Attach Codeblock CRC */
crc_attach(&q->crc_cb, cb_in, rlen); crc_attach(&q->crc_cb, q->cb_in, rlen);
} }
if (VERBOSE_ISDEBUG()) { if (VERBOSE_ISDEBUG()) {
DEBUG("CB#%d Len=%d: ", i, cb_len); DEBUG("CB#%d Len=%d: ", i, cb_len);
vec_fprint_b(stdout, cb_in, cb_len); vec_fprint_b(stdout, q->cb_in, cb_len);
} }
/* Turbo Encoding */ /* Turbo Encoding */
tcod_encode(&q->encoder, cb_in, q->cb_out, cb_len); tcod_encode(&q->encoder, q->cb_in, (char*) q->cb_out, cb_len);
} }
/* Rate matching */ /* Rate matching */
if (rm_turbo_tx(harq_process->pdsch_w_buff_c[i], harq_process->w_buff_size, if (rm_turbo_tx(harq_process->pdsch_w_buff_c[i], harq_process->w_buff_size,
q->cb_out, 3 * cb_len + 12, (char*) q->cb_out, 3 * cb_len + 12,
&e_bits[wp], n_e, rv_idx)) &e_bits[wp], n_e, rv_idx))
{ {
fprintf(stderr, "Error in rate matching\n"); fprintf(stderr, "Error in rate matching\n");
@ -778,7 +778,7 @@ int pdsch_encode(pdsch_t *q, char *data, cf_t *sf_symbols[MAX_PORTS], uint32_t s
nof_symbols = harq_process->prb_alloc.re_sf[subframe]; nof_symbols = harq_process->prb_alloc.re_sf[subframe];
nof_bits_e = nof_symbols * q->mod[harq_process->mcs.mod - 1].nbits_x_symbol; nof_bits_e = nof_symbols * q->mod[harq_process->mcs.mod - 1].nbits_x_symbol;
if (harq_process->mcs.mod == MOD_NULL) { if (harq_process->mcs.tbs == 0) {
return LIBLTE_ERROR_INVALID_INPUTS; return LIBLTE_ERROR_INVALID_INPUTS;
} }
@ -808,6 +808,7 @@ int pdsch_encode(pdsch_t *q, char *data, cf_t *sf_symbols[MAX_PORTS], uint32_t s
return LIBLTE_ERROR; return LIBLTE_ERROR;
} }
scrambling_b_offset(&q->seq_pdsch[subframe], (char*) q->pdsch_e, 0, nof_bits_e); scrambling_b_offset(&q->seq_pdsch[subframe], (char*) q->pdsch_e, 0, nof_bits_e);
mod_modulate(&q->mod[harq_process->mcs.mod - 1], (char*) q->pdsch_e, q->pdsch_d, nof_bits_e); mod_modulate(&q->mod[harq_process->mcs.mod - 1], (char*) q->pdsch_e, q->pdsch_d, nof_bits_e);

@ -76,7 +76,7 @@ int phich_init(phich_t *q, regs_t *regs, lte_cell_t cell) {
q->cell = cell; q->cell = cell;
q->regs = regs; q->regs = regs;
if (modem_table_std(&q->mod, LTE_BPSK, false)) { if (modem_table_lte(&q->mod, LTE_BPSK, false)) {
goto clean; goto clean;
} }

@ -391,79 +391,44 @@ uint32_t ra_type2_n_vrb_dl(uint32_t nof_prb, bool ngap_is_1) {
} }
} }
/* Converts ra_mcs_t structure to MCS index for both Uplink and Downlink */
uint32_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 LIBLTE_SUCCESS;
}
}
uint32_t ra_mod_bits_x_symbol(ra_mod_t mod) {
switch(mod) {
case BPSK:
return 1;
case QPSK:
return 2;
case QAM16:
return 4;
case QAM64:
return 6;
default:
return 0;
}
return 0;
}
/* Converts MCS index to ra_mcs_t structure for Downlink as defined inTable 7.1.7.1-1 on 36.213 */ /* 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(uint32_t idx, ra_mcs_t *mcs) { int ra_mcs_from_idx_dl(uint32_t mcs_idx, uint32_t nof_prb, ra_mcs_t *mcs) {
if (idx < 10) { if (mcs_idx < 10) {
mcs->mod = QPSK; mcs->mod = LTE_QPSK;
mcs->tbs_idx = idx; mcs->tbs = ra_tbs_from_idx(mcs_idx, nof_prb);
} else if (idx < 17) { } else if (mcs_idx < 17) {
mcs->mod = QAM16; mcs->mod = LTE_QAM16;
mcs->tbs_idx = idx - 1; mcs->tbs = ra_tbs_from_idx(mcs_idx - 1, nof_prb);
} else if (idx < 29) { } else if (mcs_idx < 29) {
mcs->mod = QAM64; mcs->mod = LTE_QAM64;
mcs->tbs_idx = idx - 2; mcs->tbs = ra_tbs_from_idx(mcs_idx - 2, nof_prb);
} else if (idx == 29) { } else if (mcs_idx == 29) {
mcs->mod = QPSK; mcs->mod = LTE_QPSK;
mcs->tbs_idx = 0; mcs->tbs = 0;
} else if (idx == 30) { } else if (mcs_idx == 30) {
mcs->mod = QAM16; mcs->mod = LTE_QAM16;
mcs->tbs_idx = 0; mcs->tbs = 0;
} else if (idx == 31) { } else if (mcs_idx == 31) {
mcs->mod = QAM64; mcs->mod = LTE_QAM64;
mcs->tbs_idx = 0; mcs->tbs = 0;
} else { } else {
mcs->mod = MOD_NULL;
mcs->tbs_idx = 0;
return LIBLTE_ERROR; return LIBLTE_ERROR;
} }
return LIBLTE_SUCCESS; return LIBLTE_SUCCESS;
} }
/* Converts MCS index to ra_mcs_t structure for Uplink as defined in Table 8.6.1-1 on 36.213 */ /* 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(uint32_t idx, ra_mcs_t *mcs) { int ra_mcs_from_idx_ul(uint32_t mcs_idx, uint32_t nof_prb, ra_mcs_t *mcs) {
if (idx < 11) { if (mcs_idx < 11) {
mcs->mod = QPSK; mcs->mod = LTE_QPSK;
mcs->tbs_idx = idx; mcs->tbs = ra_tbs_from_idx(mcs_idx, nof_prb);
} else if (idx < 21) { } else if (mcs_idx < 21) {
mcs->mod = QAM16; mcs->mod = LTE_QAM16;
mcs->tbs_idx = idx - 1; mcs->tbs = ra_tbs_from_idx(mcs_idx - 1, nof_prb);
} else if (idx < 29) { } else if (mcs_idx < 29) {
mcs->mod = QAM64; mcs->mod = LTE_QAM64;
mcs->tbs_idx = idx - 2; mcs->tbs = ra_tbs_from_idx(mcs_idx - 2, nof_prb);
} else { } else {
mcs->mod = MOD_NULL;
mcs->tbs_idx = 0;
return LIBLTE_ERROR; return LIBLTE_ERROR;
} }
return LIBLTE_SUCCESS; return LIBLTE_SUCCESS;
@ -478,22 +443,6 @@ int ra_tbs_from_idx_format1c(uint32_t tbs_idx) {
} }
} }
/* 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(uint32_t tbs) {
int idx;
if (tbs < tbs_format1c_table[0]) {
return LIBLTE_ERROR;
}
for (idx = 1; idx < 32; idx++) {
if (tbs_format1c_table[idx - 1] <= tbs && tbs_format1c_table[idx] >= tbs) {
return idx;
}
}
return LIBLTE_ERROR;
}
/* Downlink Transport Block size determination as defined in 7.1.7.2 on 36.213 */ /* Downlink Transport Block size determination as defined in 7.1.7.2 on 36.213 */
int ra_tbs_from_idx(uint32_t tbs_idx, uint32_t n_prb) { int ra_tbs_from_idx(uint32_t tbs_idx, uint32_t n_prb) {
if (tbs_idx < 27 && n_prb > 0 && n_prb <= MAX_PRB) { if (tbs_idx < 27 && n_prb > 0 && n_prb <= MAX_PRB) {
@ -507,7 +456,7 @@ int ra_tbs_from_idx(uint32_t tbs_idx, uint32_t n_prb) {
* or -1 if the TBS value is not within the valid TBS values * or -1 if the TBS value is not within the valid TBS values
*/ */
int ra_tbs_to_table_idx(uint32_t tbs, uint32_t n_prb) { int ra_tbs_to_table_idx(uint32_t tbs, uint32_t n_prb) {
int idx; uint32_t idx;
if (n_prb > 0 && n_prb <= MAX_PRB) { if (n_prb > 0 && n_prb <= MAX_PRB) {
return LIBLTE_ERROR; return LIBLTE_ERROR;
} }
@ -522,19 +471,6 @@ int ra_tbs_to_table_idx(uint32_t tbs, uint32_t n_prb) {
return LIBLTE_ERROR; return LIBLTE_ERROR;
} }
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, uint32_t nof_prb) { void ra_pusch_fprint(FILE *f, ra_pusch_t *ra, uint32_t nof_prb) {
fprintf(f, "Frequency Hopping:\t"); fprintf(f, "Frequency Hopping:\t");
if (ra->freq_hop_fl == hop_disabled) { if (ra->freq_hop_fl == hop_disabled) {
@ -558,15 +494,6 @@ char *ra_type_string(ra_type_t alloc_type) {
} }
} }
void ra_pdsch_set_mcs_index(ra_pdsch_t *ra, uint32_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, uint32_t tbs_idx) {
ra->mcs.mod = mod;
ra->mcs.tbs_idx = tbs_idx;
ra->mcs.tbs = 0;
}
void ra_pdsch_fprint(FILE *f, ra_pdsch_t *ra, uint32_t nof_prb) { void ra_pdsch_fprint(FILE *f, ra_pdsch_t *ra, uint32_t nof_prb) {
fprintf(f, " - Resource Allocation Type:\t\t%s\n", fprintf(f, " - Resource Allocation Type:\t\t%s\n",
@ -609,8 +536,8 @@ void ra_pdsch_fprint(FILE *f, ra_pdsch_t *ra, uint32_t nof_prb) {
} }
fprintf(f, " - Number of PRBs:\t\t\t%d\n", ra_nprb_dl(ra, nof_prb)); 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 and coding scheme index:\t%d\n", ra->mcs_idx);
fprintf(f, " - Modulation type:\t\t\t%s\n", ra_mod_string(ra->mcs.mod)); fprintf(f, " - Modulation type:\t\t\t%s\n", lte_mod_string(ra->mcs.mod));
fprintf(f, " - Transport block size:\t\t%d\n", ra->mcs.tbs); 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, " - 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, " - New data indicator:\t\t\t%s\n", ra->ndi ? "Yes" : "No");

@ -292,7 +292,7 @@ int main(int argc, char **argv) {
ra_pdsch_fprint(stdout, &ra_dl, cell.nof_prb); ra_pdsch_fprint(stdout, &ra_dl, cell.nof_prb);
if (ra_dl.alloc_type == alloc_type2 && ra_dl.type2_alloc.mode == t2_loc 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.type2_alloc.riv == 11 && ra_dl.rv_idx == 0
&& ra_dl.harq_process == 0 && ra_dl.mcs.mcs_idx == 2) { && ra_dl.harq_process == 0 && ra_dl.mcs_idx == 2) {
printf("This is the file signal.1.92M.amar.dat\n"); printf("This is the file signal.1.92M.amar.dat\n");
ret = 0; ret = 0;
} }

@ -160,7 +160,7 @@ int main(int argc, char **argv) {
nof_dcis = 2; nof_dcis = 2;
bzero(&ra_dl, sizeof(ra_pdsch_t)); bzero(&ra_dl, sizeof(ra_pdsch_t));
ra_dl.harq_process = 0; ra_dl.harq_process = 0;
ra_pdsch_set_mcs(&ra_dl, QAM16, 5); ra_dl.mcs_idx = 5;
ra_dl.ndi = 0; ra_dl.ndi = 0;
ra_dl.rv_idx = 0; ra_dl.rv_idx = 0;
ra_dl.alloc_type = alloc_type0; ra_dl.alloc_type = alloc_type0;
@ -169,7 +169,7 @@ int main(int argc, char **argv) {
dci_msg_pack_pdsch(&ra_dl, &dci_tx[0], Format1, cell.nof_prb, false); dci_msg_pack_pdsch(&ra_dl, &dci_tx[0], Format1, cell.nof_prb, false);
dci_location_set(&dci_locations[0], 0, 0); dci_location_set(&dci_locations[0], 0, 0);
ra_pdsch_set_mcs(&ra_dl, QAM16, 15); ra_dl.mcs_idx = 15;
dci_msg_pack_pdsch(&ra_dl, &dci_tx[1], Format1, cell.nof_prb, false); dci_msg_pack_pdsch(&ra_dl, &dci_tx[1], Format1, cell.nof_prb, false);
dci_location_set(&dci_locations[1], 0, 1); dci_location_set(&dci_locations[1], 0, 1);

@ -223,7 +223,6 @@ void base_free() {
int main(int argc, char **argv) { int main(int argc, char **argv) {
ra_pdsch_t ra_dl; ra_pdsch_t ra_dl;
ra_prb_t prb_alloc;
int i; int i;
int nof_frames; int nof_frames;
int ret; int ret;
@ -300,39 +299,11 @@ int main(int argc, char **argv) {
} }
if (crc_rem == rnti) { if (crc_rem == rnti) {
dci_msg_type_t type; if (dci_msg_to_ra_dl(&dci_msg, rnti, 1234, cell, cfi, &ra_dl)) {
if (dci_msg_get_type(&dci_msg, &type, cell.nof_prb, rnti, 1234)) { fprintf(stderr, "Error unpacking PDSCH scheduling DCI message\n");
fprintf(stderr, "Can't get DCI message type\n");
goto goout; goto goout;
} }
if (pdsch_harq_setup(&harq_process, ra_dl.mcs, &ra_dl.prb_alloc)) {
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_msg, &ra_dl, cell.nof_prb, rnti != SIRNTI)) {
fprintf(stderr, "Can't unpack PDSCH message\n");
} else {
ra_pdsch_fprint(stdout, &ra_dl, cell.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;
}
if (ra_prb_get_dl(&prb_alloc, &ra_dl, cell.nof_prb)) {
fprintf(stderr, "Error computing resource allocation\n");
goto goout;
}
ra_prb_get_re_dl(&prb_alloc, cell.nof_prb, cell.nof_ports, cell.nof_prb<10?(cfi+1):cfi, cell.cp);
if (pdsch_harq_setup(&harq_process, ra_dl.mcs, &prb_alloc)) {
fprintf(stderr, "Error configuring HARQ process\n"); fprintf(stderr, "Error configuring HARQ process\n");
goto goout; goto goout;
} }
@ -348,6 +319,8 @@ int main(int argc, char **argv) {
nof_frames++; nof_frames++;
} while (nof_frames <= max_frames); } while (nof_frames <= max_frames);
ret = 0;
goout: goout:
base_free(); base_free();
exit(ret); exit(ret);

@ -44,7 +44,7 @@ lte_cell_t cell = {
uint32_t cfi = 1; uint32_t cfi = 1;
uint32_t tbs = 0; uint32_t tbs = 0;
uint32_t subframe = 1; uint32_t subframe = 1;
ra_mod_t modulation = BPSK; lte_mod_t modulation = LTE_BPSK;
uint32_t rv_idx = 0; uint32_t rv_idx = 0;
void usage(char *prog) { void usage(char *prog) {
@ -66,16 +66,16 @@ void parse_args(int argc, char **argv) {
case 'm': case 'm':
switch(atoi(argv[optind])) { switch(atoi(argv[optind])) {
case 1: case 1:
modulation = BPSK; modulation = LTE_BPSK;
break; break;
case 2: case 2:
modulation = QPSK; modulation = LTE_QPSK;
break; break;
case 4: case 4:
modulation = QAM16; modulation = LTE_QAM16;
break; break;
case 6: case 6:
modulation = QAM64; modulation = LTE_QAM64;
break; break;
default: default:
fprintf(stderr, "Invalid modulation %d. Possible values: " fprintf(stderr, "Invalid modulation %d. Possible values: "

Loading…
Cancel
Save