Added lte_cell_t struct to PBCH module.

master
ismagom 11 years ago
parent 5eab57670b
commit 231c29ef21

@ -38,10 +38,16 @@
void *uhd;
#endif
lte_cell_t cell = {
6, // nof_prb
1, // nof_ports
1, // cell_id
CPNORM // cyclic prefix
};
char *output_file_name = NULL;
int nof_frames=-1;
int cell_id = 1;
int nof_prb = 6;
char *uhd_args = "";
float uhd_amp=0.25, uhd_gain=10.0, uhd_freq=2400000000;
@ -51,7 +57,7 @@ lte_fft_t ifft;
pbch_t pbch;
cf_t *sf_buffer = NULL, *output_buffer = NULL;
int slot_n_re, slot_n_samples;
int sf_n_re, sf_n_samples;
#define UHD_SAMP_FREQ 1920000
@ -67,8 +73,8 @@ void usage(char *prog) {
#endif
printf("\t-o output_file [Default USRP]\n");
printf("\t-n number of frames [Default %d]\n", nof_frames);
printf("\t-c cell id [Default %d]\n", cell_id);
printf("\t-p nof_prb [Default %d]\n", nof_prb);
printf("\t-c cell id [Default %d]\n", cell.id);
printf("\t-p nof_prb [Default %d]\n", cell.nof_prb);
printf("\t-v [set verbose to debug, default none]\n");
}
@ -95,10 +101,10 @@ void parse_args(int argc, char **argv) {
nof_frames = atoi(argv[optind]);
break;
case 'p':
nof_prb = atoi(argv[optind]);
cell.nof_prb = atoi(argv[optind]);
break;
case 'c':
cell_id = atoi(argv[optind]);
cell.id = atoi(argv[optind]);
break;
case 'v':
verbose++;
@ -118,12 +124,12 @@ void parse_args(int argc, char **argv) {
void base_init() {
/* init memory */
sf_buffer = malloc(sizeof(cf_t) * slot_n_re);
sf_buffer = malloc(sizeof(cf_t) * sf_n_re);
if (!sf_buffer) {
perror("malloc");
exit(-1);
}
output_buffer = malloc(sizeof(cf_t) * slot_n_samples);
output_buffer = malloc(sizeof(cf_t) * sf_n_samples);
if (!output_buffer) {
perror("malloc");
exit(-1);
@ -148,11 +154,11 @@ void base_init() {
}
/* create ifft object */
if (lte_ifft_init(&ifft, CPNORM, nof_prb)) {
if (lte_ifft_init(&ifft, CPNORM, cell.nof_prb)) {
fprintf(stderr, "Error creating iFFT object\n");
exit(-1);
}
if (pbch_init(&pbch, 6, cell_id, CPNORM)) {
if (pbch_init(&pbch, cell)) {
fprintf(stderr, "Error creating PBCH object\n");
exit(-1);
}
@ -180,14 +186,14 @@ void base_free() {
}
int main(int argc, char **argv) {
int nf, ns, N_id_2;
int nf, sf_idx, N_id_2;
cf_t pss_signal[PSS_LEN];
float sss_signal0[SSS_LEN]; // for subframe 0
float sss_signal5[SSS_LEN]; // for subframe 5
pbch_mib_t mib;
refsignal_t refs[NSLOTS_X_FRAME];
int i;
cf_t *slot1_symbols[MAX_PORTS];
int i, n;
cf_t *sf_symbols[MAX_PORTS];
#ifdef DISABLE_UHD
@ -199,20 +205,20 @@ int main(int argc, char **argv) {
parse_args(argc,argv);
N_id_2 = cell_id%3;
slot_n_re = CPNORM_NSYMB * nof_prb * RE_X_RB;
slot_n_samples = SLOT_LEN_CPNORM(lte_symbol_sz(nof_prb));
N_id_2 = cell.id%3;
sf_n_re = 2 * CPNORM_NSYMB * cell.nof_prb * RE_X_RB;
sf_n_samples = 2 * SLOT_LEN_CPNORM(lte_symbol_sz(cell.nof_prb));
/* this *must* be called after setting slot_len_* */
base_init();
/* Generate PSS/SSS signals */
pss_generate(pss_signal, N_id_2);
sss_generate(sss_signal0, sss_signal5, cell_id);
sss_generate(sss_signal0, sss_signal5, cell.id);
/* Generate CRS signals */
lte_cell_t cell;
cell.id = cell_id;
cell.id = cell.id;
cell.nof_prb = 6;
cell.cp = CPNORM;
cell.nof_ports = 1;
@ -224,14 +230,14 @@ int main(int argc, char **argv) {
}
}
mib.nof_ports = 1;
mib.nof_prb = 6;
mib.nof_ports = cell.nof_ports;
mib.nof_prb = cell.nof_prb;
mib.phich_length = PHICH_NORM;
mib.phich_resources = R_1;
mib.sfn = 0;
for (i=0;i<MAX_PORTS;i++) { // now there's only 1 port
slot1_symbols[i] = sf_buffer;
sf_symbols[i] = sf_buffer;
}
#ifndef DISABLE_UHD
@ -245,35 +251,33 @@ int main(int argc, char **argv) {
nf = 0;
while(nf<nof_frames || nof_frames == -1) {
for (ns=0;ns<NSLOTS_X_FRAME;ns++) {
bzero(sf_buffer, sizeof(cf_t) * slot_n_re);
switch(ns) {
case 0: // tx pss/sss
case 10: // tx pss/sss
pss_put_slot(pss_signal, sf_buffer, nof_prb, CPNORM);
sss_put_slot(ns?sss_signal5:sss_signal0, sf_buffer, nof_prb, CPNORM);
break;
case 1: // tx pbch
pbch_encode(&pbch, &mib, slot1_symbols, 1);
break;
default: // transmit zeros
break;
for (sf_idx=0;sf_idx<NSUBFRAMES_X_FRAME;sf_idx++) {
bzero(sf_buffer, sizeof(cf_t) * sf_n_re);
if (sf_idx == 0 || sf_idx == 5) {
pss_put_slot(pss_signal, sf_buffer, cell.nof_prb, CPNORM);
sss_put_slot(sf_idx?sss_signal5:sss_signal0, sf_buffer, cell.nof_prb, CPNORM);
}
if (sf_idx == 0) {
pbch_encode(&pbch, &mib, sf_symbols);
}
refsignal_put(&refs[ns], sf_buffer);
for (n=0;n<2;n++) {
refsignal_put(&refs[2*sf_idx+n], &sf_buffer[n*sf_n_re/2]);
}
/* Transform to OFDM symbols */
lte_ifft_run_slot(&ifft, sf_buffer, output_buffer);
lte_ifft_run_sf(&ifft, sf_buffer, output_buffer);
/* send to file or usrp */
if (output_file_name) {
filesink_write(&fsink, output_buffer, slot_n_samples);
filesink_write(&fsink, output_buffer, sf_n_samples);
usleep(5000);
} else {
#ifndef DISABLE_UHD
vec_sc_prod_cfc(output_buffer, uhd_amp, output_buffer, slot_n_samples);
cuhd_send(uhd, output_buffer, slot_n_samples, 1);
vec_sc_prod_cfc(output_buffer, uhd_amp, output_buffer, sf_n_samples);
cuhd_send(uhd, output_buffer, sf_n_samples, 1);
#endif
}
}

@ -57,7 +57,7 @@ plot_scatter_t pscatrecv, pscatequal;
#define NOF_PORTS 2
float find_threshold = 20.0;
float find_threshold = 9.0;
int max_track_lost = 20, nof_frames = -1;
int track_len = 300;
char *input_file_name = NULL;
@ -81,7 +81,7 @@ enum sync_state {
};
void usage(char *prog) {
printf("Usage: %s [iagfndvp]\n", prog);
printf("Usage: %s [iagfndvt]\n", prog);
printf("\t-i input_file [Default use USRP]\n");
#ifndef DISABLE_UHD
printf("\t-a UHD args [Default %s]\n", uhd_args);
@ -90,8 +90,9 @@ void usage(char *prog) {
#else
printf("\t UHD is disabled. CUHD library not available\n");
#endif
printf("\t-n nof_frames [Default %d]\n", nof_frames);
printf("\t-p PSS threshold [Default %f]\n", find_threshold);
printf("\t-t PSS threshold [Default %f]\n", find_threshold);
#ifndef DISABLE_GRAPHICS
printf("\t-d disable plots [Default enabled]\n");
#else
@ -102,7 +103,7 @@ void usage(char *prog) {
void parse_args(int argc, char **argv) {
int opt;
while ((opt = getopt(argc, argv, "iagfndvp")) != -1) {
while ((opt = getopt(argc, argv, "iagfndvt")) != -1) {
switch (opt) {
case 'i':
input_file_name = argv[optind];
@ -116,7 +117,7 @@ void parse_args(int argc, char **argv) {
case 'f':
uhd_freq = atof(argv[optind]);
break;
case 'p':
case 't':
find_threshold = atof(argv[optind]);
break;
case 'n':
@ -274,11 +275,11 @@ int mib_decoder_init(int cell_id) {
return -1;
}
if (pbch_init(&pbch, 6, cell_id, CPNORM)) {
if (pbch_init(&pbch, cell)) {
fprintf(stderr, "Error initiating PBCH\n");
return -1;
}
DEBUG("PBCH initiated cell_id=%d\n", cell_id);
DEBUG("PBCH initiated cell_id=%d\n", cell.id);
return 0;
}

@ -39,12 +39,18 @@ void *uhd;
#endif
char *output_file_name = NULL;
int nof_frames = -1;
int cell_id = 1;
int nof_prb = 6;
char *uhd_args = "";
lte_cell_t cell = {
6, // nof_prb
1, // nof_ports
1, // cell_id
CPNORM // cyclic prefix
};
uint8_t cfi=1;
int nof_frames = -1;
char *uhd_args = "";
float uhd_amp = 0.25, uhd_gain = 10.0, uhd_freq = 2400000000;
filesink_t fsink;
@ -70,8 +76,8 @@ void usage(char *prog) {
#endif
printf("\t-o output_file [Default USRP]\n");
printf("\t-n number of frames [Default %d]\n", nof_frames);
printf("\t-c cell id [Default %d]\n", cell_id);
printf("\t-p nof_prb [Default %d]\n", nof_prb);
printf("\t-c cell id [Default %d]\n", cell.id);
printf("\t-p nof_prb [Default %d]\n", cell.nof_prb);
printf("\t-v [set verbose to debug, default none]\n");
}
@ -98,10 +104,10 @@ void parse_args(int argc, char **argv) {
nof_frames = atoi(argv[optind]);
break;
case 'p':
nof_prb = atoi(argv[optind]);
cell.nof_prb = atoi(argv[optind]);
break;
case 'c':
cell_id = atoi(argv[optind]);
cell.id = atoi(argv[optind]);
break;
case 'v':
verbose++;
@ -120,12 +126,6 @@ void parse_args(int argc, char **argv) {
}
void base_init() {
lte_cell_t cell;
cell.id = cell_id;
cell.nof_ports = 1;
cell.nof_prb = nof_prb;
cell.cp = CPNORM;
/* init memory */
sf_buffer = malloc(sizeof(cf_t) * sf_n_re);
@ -158,11 +158,11 @@ void base_init() {
}
/* create ifft object */
if (lte_ifft_init(&ifft, CPNORM, nof_prb)) {
if (lte_ifft_init(&ifft, CPNORM, cell.nof_prb)) {
fprintf(stderr, "Error creating iFFT object\n");
exit(-1);
}
if (pbch_init(&pbch, nof_prb, cell_id, CPNORM)) {
if (pbch_init(&pbch, cell)) {
fprintf(stderr, "Error creating PBCH object\n");
exit(-1);
}
@ -229,7 +229,6 @@ int main(int argc, char **argv) {
int i, n;
char *data;
cf_t *sf_symbols[MAX_PORTS];
cf_t *slot1_symbols[MAX_PORTS];
dci_t dci_tx;
#ifdef DISABLE_UHD
@ -241,23 +240,16 @@ int main(int argc, char **argv) {
parse_args(argc, argv);
N_id_2 = cell_id % 3;
sf_n_re = 2 * CPNORM_NSYMB * nof_prb * RE_X_RB;
sf_n_samples = 2 * SLOT_LEN_CPNORM(lte_symbol_sz(nof_prb));
N_id_2 = cell.id % 3;
sf_n_re = 2 * CPNORM_NSYMB * cell.nof_prb * RE_X_RB;
sf_n_samples = 2 * SLOT_LEN_CPNORM(lte_symbol_sz(cell.nof_prb));
/* this *must* be called after setting slot_len_* */
base_init();
/* Generate PSS/SSS signals */
pss_generate(pss_signal, N_id_2);
sss_generate(sss_signal0, sss_signal5, cell_id);
lte_cell_t cell;
cell.id = cell_id;
cell.nof_ports = 1;
cell.nof_prb = nof_prb;
cell.cp = CPNORM;
sss_generate(sss_signal0, sss_signal5, cell.id);
/* Generate CRS signals */
for (i = 0; i < NSLOTS_X_FRAME; i++) {
@ -267,21 +259,20 @@ int main(int argc, char **argv) {
}
}
mib.nof_ports = 1;
mib.nof_prb = nof_prb;
mib.nof_ports = cell.nof_ports;
mib.nof_prb = cell.nof_prb;
mib.phich_length = PHICH_NORM;
mib.phich_resources = R_1;
mib.sfn = 0;
for (i = 0; i < MAX_PORTS; i++) { // now there's only 1 port
sf_symbols[i] = sf_buffer;
slot1_symbols[i] = &sf_buffer[sf_n_re/2];
}
#ifndef DISABLE_UHD
if (!output_file_name) {
printf("Set TX rate: %.2f MHz\n",
cuhd_set_tx_srate(uhd, lte_sampling_freq_hz(nof_prb)) / 1000000);
cuhd_set_tx_srate(uhd, lte_sampling_freq_hz(cell.nof_prb)) / 1000000);
printf("Set TX gain: %.1f dB\n", cuhd_set_tx_gain(uhd, uhd_gain));
printf("Set TX freq: %.2f MHz\n",
cuhd_set_tx_freq(uhd, uhd_freq) / 1000000);
@ -297,16 +288,16 @@ int main(int argc, char **argv) {
ra_dl.alloc_type = alloc_type0;
ra_dl.type0_alloc.rbg_bitmask = 0xffffffff;
dci_msg_pack_pdsch(&ra_dl, &dci_tx.msg[0], Format1, nof_prb, false);
dci_msg_pack_pdsch(&ra_dl, &dci_tx.msg[0], Format1, cell.nof_prb, false);
dci_tx.nof_dcis++;
pdcch_init_search_ue(&pdcch, 1234, cfi);
ra_prb_get_dl(&prb_alloc, &ra_dl, nof_prb);
ra_prb_get_re(&prb_alloc, nof_prb, 1, nof_prb<10?(cfi+1):cfi, CPNORM);
ra_dl.mcs.tbs = ra_tbs_from_idx(ra_dl.mcs.tbs_idx, 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_dl.mcs.tbs = ra_tbs_from_idx(ra_dl.mcs.tbs_idx, cell.nof_prb);
ra_pdsch_fprint(stdout, &ra_dl, nof_prb);
ra_pdsch_fprint(stdout, &ra_dl, cell.nof_prb);
data = malloc(sizeof(char) * ra_dl.mcs.tbs);
if (!data) {
@ -321,13 +312,13 @@ int main(int argc, char **argv) {
bzero(sf_buffer, sizeof(cf_t) * sf_n_re);
if (sf_idx == 0 || sf_idx == 5) {
pss_put_slot(pss_signal, sf_buffer, nof_prb, CPNORM);
sss_put_slot(sf_idx ? sss_signal5 : sss_signal0, sf_buffer, nof_prb,
pss_put_slot(pss_signal, sf_buffer, cell.nof_prb, CPNORM);
sss_put_slot(sf_idx ? sss_signal5 : sss_signal0, sf_buffer, cell.nof_prb,
CPNORM);
}
if (sf_idx == 0) {
pbch_encode(&pbch, &mib, slot1_symbols, 1);
pbch_encode(&pbch, &mib, sf_symbols);
}
for (n=0;n<2;n++) {

@ -55,7 +55,7 @@ plot_scatter_t pscatrecv, pscatequal;
#define NOF_PORTS 2
float find_threshold = 10.0;
float find_threshold = 9.0;
int nof_frames = -1;
int pdsch_errors = 0, pdsch_total = 0;
int frame_cnt;
@ -362,7 +362,7 @@ int cell_id_init(int nof_prb, int cell_id) {
cell.id = cell_id;
cell.nof_prb = 6;
cell.nof_ports = MAX_PORTS;
cell.nof_ports = 2;
cell.cp = CPNORM;
if (chest_ref_LTEDL(&chest, cell)) {
@ -370,7 +370,7 @@ int cell_id_init(int nof_prb, int cell_id) {
return -1;
}
if (pbch_init(&pbch, nof_prb, cell_id, CPNORM)) {
if (pbch_init(&pbch, cell)) {
fprintf(stderr, "Error initiating PBCH\n");
return -1;
}
@ -447,7 +447,7 @@ int rx_run(cf_t *input, int sf_idx) {
fprintf(stderr, "Error computing resource allocation\n");
break;
}
ra_prb_get_re(&prb_alloc, cell.nof_prb, cell.nof_ports,
ra_prb_get_re_dl(&prb_alloc, cell.nof_prb, cell.nof_ports,
cell.nof_prb<10?(cfi+1):cfi, CPNORM);
if (pdsch_decode(&pdsch, fft_buffer, ce, data, sf_idx, ra_dl.mcs, &prb_alloc)) {
@ -482,19 +482,13 @@ int rx_run(cf_t *input, int sf_idx) {
}
int mib_decoder_run(cf_t *input, pbch_mib_t *mib) {
int i, n;
lte_fft_run_slot(&fft, input, fft_buffer);
lte_fft_run_sf(&fft, input, fft_buffer);
/* Get channel estimates for each port */
for (i = 0; i < NOF_PORTS; i++) {
chest_ce_slot_port(&chest, fft_buffer, ce[i], 1, i);
}
chest_ce_sf(&chest, fft_buffer, ce, 0);
DEBUG("Decoding PBCH\n", 0);
n = pbch_decode(&pbch, fft_buffer, ce, mib);
return n;
return pbch_decode(&pbch, fft_buffer, ce, mib);
}
int run_receiver(cf_t *input, int cell_id, int sf_idx) {
@ -506,7 +500,7 @@ int run_receiver(cf_t *input, int cell_id, int sf_idx) {
if (!cell.nof_prb) {
if (!sf_idx) {
if (mib_decoder_run(&input[sf_n_samples/2], &mib)) {
if (mib_decoder_run(input, &mib)) {
INFO("MIB decoded!\n", 0);
cell.id = cell_id;
cell.cp = CPNORM;

@ -314,7 +314,7 @@ int mib_decoder_init(int cell_id) {
lte_cell_t cell;
cell.id = cell_id;
cell.nof_prb = 6;
cell.nof_ports = MAX_PORTS;
cell.nof_ports = 2;
cell.cp = CPNORM;
if (chest_ref_LTEDL(&chest, cell)) {
@ -322,7 +322,7 @@ int mib_decoder_init(int cell_id) {
return -1;
}
if (pbch_init(&pbch, 6, cell_id, CPNORM)) {
if (pbch_init(&pbch, cell)) {
fprintf(stderr, "Error initiating PBCH\n");
return -1;
}

@ -30,6 +30,7 @@
#define CRC_
#include "liblte/config.h"
#include <stdint.h>
typedef struct LIBLTE_API {
unsigned long table[256];
@ -45,6 +46,6 @@ typedef struct LIBLTE_API {
LIBLTE_API int crc_init(crc_t *h, unsigned int crc_poly, int crc_order);
LIBLTE_API int crc_set_init(crc_t *h, unsigned long crc_init_value);
LIBLTE_API void crc_attach(crc_t *h, char *data, int len);
LIBLTE_API unsigned int crc_checksum(crc_t *h, char *data, int len);
LIBLTE_API uint32_t crc_checksum(crc_t *h, char *data, int len);
#endif

@ -47,19 +47,18 @@
typedef _Complex float cf_t;
typedef struct LIBLTE_API {
int nof_ports;
int nof_prb;
int sfn;
uint8_t nof_ports;
uint8_t nof_prb;
uint32_t sfn;
phich_length_t phich_length;
phich_resources_t phich_resources;
}pbch_mib_t;
/* PBCH object */
typedef struct LIBLTE_API {
int cell_id;
lte_cp_t cp;
int nof_prb;
int nof_symbols;
lte_cell_t cell;
uint8_t nof_symbols;
/* buffers */
cf_t *ce[MAX_PORTS];
@ -73,7 +72,7 @@ typedef struct LIBLTE_API {
char *data;
char *data_enc;
int frame_idx;
uint8_t frame_idx;
/* tx & rx objects */
modem_table_t mod;
@ -83,23 +82,20 @@ typedef struct LIBLTE_API {
crc_t crc;
convcoder_t encoder;
}pbch_t;
} pbch_t;
LIBLTE_API int pbch_init(pbch_t *q,
int nof_prb,
int cell_id,
lte_cp_t cp);
lte_cell_t cell);
LIBLTE_API void pbch_free(pbch_t *q);
LIBLTE_API int pbch_decode(pbch_t *q,
cf_t *slot1_symbols,
cf_t *sf_symbols,
cf_t *ce[MAX_PORTS],
pbch_mib_t *mib);
LIBLTE_API void pbch_encode(pbch_t *q,
LIBLTE_API int pbch_encode(pbch_t *q,
pbch_mib_t *mib,
cf_t *slot1_symbols[MAX_PORTS],
int nof_ports);
cf_t *sf_symbols[MAX_PORTS]);
LIBLTE_API void pbch_decode_reset(pbch_t *q);

@ -46,7 +46,7 @@ typedef struct LIBLTE_API {
// 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
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;
@ -64,9 +64,9 @@ typedef struct LIBLTE_API {
} ra_type1_t;
typedef struct LIBLTE_API {
uint32_t riv; // if L_crb==0, DCI message packer will take this value directly
uint16_t L_crb;
uint16_t RB_start;
uint16_t riv; // if L_crb==0, DCI message packer will take this value directly
uint8_t L_crb;
uint8_t RB_start;
enum {
nprb1a_2 = 0, nprb1a_3 = 1
} n_prb1a;
@ -79,7 +79,7 @@ typedef struct LIBLTE_API {
} ra_type2_t;
typedef struct LIBLTE_API {
unsigned short rnti;
uint16_t rnti;
ra_type_t alloc_type;
union {
ra_type0_t type0_alloc;
@ -88,7 +88,8 @@ typedef struct LIBLTE_API {
};
ra_mcs_t mcs;
uint8_t harq_process;
uint8_t rv_idx;bool ndi;
uint8_t rv_idx;
bool ndi;
} ra_pdsch_t;
typedef struct LIBLTE_API {
@ -107,60 +108,108 @@ typedef struct LIBLTE_API {
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;
bool ndi;
bool cqi_request;
} ra_pusch_t;
typedef struct LIBLTE_API {
uint8_t prb_idx[110];
int nof_prb;
uint8_t prb_idx[MAX_PRB];
uint8_t nof_prb;
} ra_prb_slot_t;
typedef struct LIBLTE_API {
ra_prb_slot_t slot[2];
int lstart;
int re_sf[NSUBFRAMES_X_FRAME];
uint8_t lstart;
uint16_t re_sf[NSUBFRAMES_X_FRAME];
} ra_prb_t;
LIBLTE_API void ra_prb_fprint(FILE *f, ra_prb_slot_t *prb);
LIBLTE_API void ra_prb_fprint(FILE *f,
ra_prb_slot_t *prb);
LIBLTE_API int ra_prb_get_dl(ra_prb_t *prb, ra_pdsch_t *ra, int nof_prb);
LIBLTE_API int ra_prb_get_ul(ra_prb_slot_t *prb, ra_pusch_t *ra, int nof_prb);
LIBLTE_API void ra_prb_get_re(ra_prb_t *prb_dist, int nof_prb, int nof_ports,
int nof_ctrl_symbols, lte_cp_t cp);
LIBLTE_API int ra_prb_get_dl(ra_prb_t *prb,
ra_pdsch_t *ra,
uint8_t nof_prb);
LIBLTE_API int ra_nprb_dl(ra_pdsch_t *ra, int nof_prb);
LIBLTE_API int ra_nprb_ul(ra_pusch_t *ra, int nof_prb);
LIBLTE_API int ra_re_x_prb(int nsubframe, int nslot, int prb_idx, int nof_prb,
int nof_ports, int nof_ctrl_symbols, lte_cp_t cp);
LIBLTE_API int ra_prb_get_ul(ra_prb_slot_t *prb,
ra_pusch_t *ra,
uint8_t nof_prb);
LIBLTE_API void ra_prb_get_re_dl(ra_prb_t *prb_dist,
uint8_t nof_prb,
uint8_t nof_ports,
uint8_t nof_ctrl_symbols,
lte_cp_t cp);
LIBLTE_API uint16_t ra_nprb_dl(ra_pdsch_t *ra,
uint8_t nof_prb);
LIBLTE_API uint16_t ra_nprb_ul(ra_pusch_t *ra,
uint8_t nof_prb);
LIBLTE_API uint8_t ra_mcs_to_table_idx(ra_mcs_t *mcs);
LIBLTE_API int ra_mcs_from_idx_dl(uint8_t idx, ra_mcs_t *mcs);
LIBLTE_API int ra_mcs_from_idx_ul(uint8_t idx, ra_mcs_t *mcs);
LIBLTE_API int ra_mcs_from_idx_dl(uint8_t idx,
ra_mcs_t *mcs);
LIBLTE_API int ra_mcs_from_idx_ul(uint8_t idx,
ra_mcs_t *mcs);
LIBLTE_API int ra_tbs_from_idx_format1c(uint8_t tbs_idx);
LIBLTE_API int ra_tbs_to_table_idx_format1c(int tbs);
LIBLTE_API int ra_tbs_from_idx(uint8_t tbs_idx, int n_prb);
LIBLTE_API int ra_tbs_to_table_idx(int tbs, int n_prb);
LIBLTE_API int ra_tbs_to_table_idx_format1c(uint32_t tbs);
LIBLTE_API int ra_tbs_from_idx(uint8_t tbs_idx,
uint8_t n_prb);
LIBLTE_API int ra_tbs_to_table_idx(uint32_t tbs,
uint8_t n_prb);
LIBLTE_API uint8_t ra_mcs_to_table_idx(ra_mcs_t *mcs);
LIBLTE_API int ra_mcs_from_idx_dl(uint8_t idx, ra_mcs_t *mcs);
LIBLTE_API int ra_mcs_from_idx_ul(uint8_t idx, ra_mcs_t *mcs);
LIBLTE_API int ra_mcs_from_idx_dl(uint8_t idx,
ra_mcs_t *mcs);
LIBLTE_API int ra_mcs_from_idx_ul(uint8_t idx,
ra_mcs_t *mcs);
LIBLTE_API char *ra_mod_string(ra_mod_t mod);
LIBLTE_API int ra_type0_P(int nof_prb);
LIBLTE_API uint8_t ra_type0_P(uint8_t nof_prb);
LIBLTE_API uint16_t ra_type2_to_riv(uint8_t L_crb,
uint8_t RB_start,
uint8_t nof_prb);
LIBLTE_API void ra_type2_from_riv(uint16_t riv,
uint8_t *L_crb,
uint8_t *RB_start,
uint8_t nof_prb,
uint8_t nof_vrb);
LIBLTE_API uint8_t ra_type2_n_vrb_dl(uint8_t nof_prb,
bool ngap_is_1);
LIBLTE_API uint8_t ra_type2_n_rb_step(uint8_t nof_prb);
LIBLTE_API uint8_t ra_type2_ngap(uint8_t nof_prb,
bool ngap_is_1);
LIBLTE_API uint8_t ra_type1_N_rb(uint8_t nof_prb);
LIBLTE_API void ra_pdsch_set_mcs_index(ra_pdsch_t *ra,
uint8_t mcs_idx);
LIBLTE_API void ra_pdsch_set_mcs(ra_pdsch_t *ra,
ra_mod_t mod,
uint8_t tbs_idx);
LIBLTE_API uint32_t ra_type2_to_riv(uint16_t L_crb, uint16_t RB_start, int nof_prb);
LIBLTE_API void ra_type2_from_riv(uint32_t riv, uint16_t *L_crb, uint16_t *RB_start,
int nof_prb, int nof_vrb);
LIBLTE_API int ra_type2_n_vrb_dl(int nof_prb, bool ngap_is_1);
LIBLTE_API int ra_type2_n_rb_step(int nof_prb);
LIBLTE_API int ra_type2_ngap(int nof_prb, bool ngap_is_1);
LIBLTE_API int ra_type1_N_rb(int nof_prb);
LIBLTE_API void ra_pdsch_fprint(FILE *f,
ra_pdsch_t *ra,
uint8_t nof_prb);
LIBLTE_API void ra_pdsch_set_mcs_index(ra_pdsch_t *ra, uint8_t mcs_idx);
LIBLTE_API void ra_pdsch_set_mcs(ra_pdsch_t *ra, ra_mod_t mod, uint8_t tbs_idx);
LIBLTE_API void ra_pdsch_fprint(FILE *f, ra_pdsch_t *ra, int nof_prb);
LIBLTE_API void ra_pusch_fprint(FILE *f, ra_pusch_t *ra, int nof_prb);
LIBLTE_API void ra_pusch_fprint(FILE *f,
ra_pusch_t *ra,
uint8_t nof_prb);
#endif /* RB_ALLOC_H_ */

@ -38,7 +38,7 @@ LIBLTE_API uint32_t bit_unpack(char **bits, int nof_bits);
LIBLTE_API void bit_pack(uint32_t value, char **bits, int nof_bits);
LIBLTE_API void bit_fprint(FILE *stream, char *bits, int nof_bits);
LIBLTE_API unsigned int bit_diff(char *x, char *y, int nbits);
LIBLTE_API int bit_count(unsigned int n);
LIBLTE_API uint8_t bit_count(uint32_t n);
#endif // BIT_

@ -55,9 +55,9 @@ const int tc_cb_sizes[NOF_TC_CB_SIZES] = { 40, 48, 56, 64, 72, 80, 88, 96, 104,
bool lte_cell_isvalid(lte_cell_t *cell) {
if (cell->id < 504 &&
cell->nof_ports > 0 &&
cell->nof_ports < 5 &&
cell->nof_ports < MAX_PORTS+1 &&
cell->nof_prb > 5 &&
cell->nof_prb < 111
cell->nof_prb < MAX_PRB+1
) {
return true;
} else {

@ -114,7 +114,7 @@ int crc_init(crc_t *h, unsigned int crc_poly, int crc_order) {
return 0;
}
unsigned int crc_checksum(crc_t *h, char *data, int len) {
uint32_t crc_checksum(crc_t *h, char *data, int len) {
int i, k, len8, res8, a = 0;
unsigned int crc = 0;
char *pter;

@ -83,7 +83,7 @@ uint8_t riv_nbits(uint8_t nof_prb) {
return (uint8_t) ceilf(log2f((float) nof_prb * ((float) nof_prb + 1) / 2));
}
const int ambiguous_sizes[10] = { 12, 14, 16, 20, 24, 26, 32, 40, 44, 56 };
const uint8_t ambiguous_sizes[10] = { 12, 14, 16, 20, 24, 26, 32, 40, 44, 56 };
bool is_ambiguous_size(uint8_t size) {
int i;
@ -115,7 +115,7 @@ uint8_t dci_format1A_sizeof(uint8_t nof_prb) {
}
uint8_t dci_format0_sizeof(uint8_t nof_prb) {
int n = dci_format0_sizeof_(nof_prb);
uint8_t n = dci_format0_sizeof_(nof_prb);
while (n < dci_format1A_sizeof(nof_prb)) {
n++;
}
@ -137,9 +137,9 @@ uint8_t dci_format1_sizeof(uint8_t nof_prb) {
}
uint8_t dci_format1C_sizeof(uint8_t nof_prb) {
int n_vrb_dl_gap1 = ra_type2_n_vrb_dl(nof_prb, true);
int n_step = ra_type2_n_rb_step(nof_prb);
uint8_t n = +riv_nbits((uint8_t) n_vrb_dl_gap1 / n_step) + 5;
uint8_t n_vrb_dl_gap1 = ra_type2_n_vrb_dl(nof_prb, true);
uint8_t n_step = ra_type2_n_rb_step(nof_prb);
uint8_t n = riv_nbits((uint8_t) n_vrb_dl_gap1 / n_step) + 5;
if (nof_prb >= 50) {
n++;
}
@ -174,7 +174,7 @@ int dci_format0_pack(ra_pusch_t *data, dci_msg_t *msg, uint8_t nof_prb) {
/* pack bits */
char *y = msg->data;
int n_ul_hop;
uint8_t n_ul_hop;
*y++ = 0; // format differentiation
if (data->freq_hop_fl == hop_disabled) { // frequency hopping
@ -193,17 +193,17 @@ int dci_format0_pack(ra_pusch_t *data, dci_msg_t *msg, uint8_t nof_prb) {
}
/* pack RIV according to 8.1 of 36.213 */
uint32_t riv;
uint16_t riv;
if (data->type2_alloc.L_crb) {
riv = ra_type2_to_riv(data->type2_alloc.L_crb, data->type2_alloc.RB_start,
nof_prb);
} else {
riv = data->type2_alloc.riv;
}
bit_pack(riv, &y, riv_nbits(nof_prb) - n_ul_hop);
bit_pack((uint32_t) riv, &y, riv_nbits(nof_prb) - n_ul_hop);
/* pack MCS according to 8.6.1 of 36.213 */
uint32_t mcs;
uint8_t mcs;
if (data->cqi_request) {
mcs = 29;
} else {
@ -224,7 +224,7 @@ int dci_format0_pack(ra_pusch_t *data, dci_msg_t *msg, uint8_t nof_prb) {
}
}
bit_pack(mcs, &y, 5);
bit_pack((uint32_t) mcs, &y, 5);
*y++ = data->ndi;
@ -241,7 +241,7 @@ int dci_format0_pack(ra_pusch_t *data, dci_msg_t *msg, uint8_t nof_prb) {
*y++ = data->cqi_request;
// Padding with zeros
int n = dci_format0_sizeof(nof_prb);
uint8_t n = dci_format0_sizeof(nof_prb);
while (y - msg->data < n) {
*y++ = 0;
}
@ -257,7 +257,7 @@ int dci_format0_unpack(dci_msg_t *msg, ra_pusch_t *data, uint8_t nof_prb) {
/* pack bits */
char *y = msg->data;
int n_ul_hop;
uint8_t n_ul_hop;
/* Make sure it's a Format0 message */
if (msg->location.nof_bits != dci_format_sizeof(Format0, nof_prb)) {
@ -283,14 +283,14 @@ int dci_format0_unpack(dci_msg_t *msg, ra_pusch_t *data, uint8_t nof_prb) {
}
}
/* unpack RIV according to 8.1 of 36.213 */
uint32_t riv = bit_unpack(&y, riv_nbits(nof_prb) - n_ul_hop);
uint16_t riv = bit_unpack(&y, riv_nbits(nof_prb) - n_ul_hop);
ra_type2_from_riv(riv, &data->type2_alloc.L_crb, &data->type2_alloc.RB_start,
nof_prb, nof_prb);
bit_pack(riv, &y, riv_nbits(nof_prb) - n_ul_hop);
bit_pack((uint32_t) riv, &y, riv_nbits(nof_prb) - n_ul_hop);
data->type2_alloc.riv = riv;
/* unpack MCS according to 8.6 of 36.213 */
uint32_t mcs = bit_unpack(&y, 5);
uint8_t mcs = bit_unpack(&y, 5);
data->ndi = *y++ ? true : false;
@ -336,16 +336,16 @@ int dci_format1_pack(ra_pdsch_t *data, dci_msg_t *msg, uint8_t nof_prb) {
}
/* Resource allocation: type0 or type 1 */
int P = ra_type0_P(nof_prb);
int alloc_size = (int) ceilf((float) nof_prb / P);
uint8_t P = ra_type0_P(nof_prb);
uint8_t alloc_size = (uint8_t) ceilf((float) nof_prb / P);
switch (data->alloc_type) {
case alloc_type0:
bit_pack(data->type0_alloc.rbg_bitmask, &y, alloc_size);
bit_pack((uint32_t) data->type0_alloc.rbg_bitmask, &y, alloc_size);
break;
case alloc_type1:
bit_pack(data->type1_alloc.rbg_subset, &y, (int) ceilf(log2f(P)));
bit_pack((uint32_t) data->type1_alloc.rbg_subset, &y, (int) ceilf(log2f(P)));
*y++ = data->type1_alloc.shift ? 1 : 0;
bit_pack(data->type1_alloc.vrb_bitmask, &y,
bit_pack((uint32_t) data->type1_alloc.vrb_bitmask, &y,
alloc_size - (int) ceilf(log2f(P)) - 1);
break;
default:
@ -355,7 +355,7 @@ int dci_format1_pack(ra_pdsch_t *data, dci_msg_t *msg, uint8_t nof_prb) {
}
/* pack MCS according to 7.1.7 of 36.213 */
uint32_t mcs;
uint8_t mcs;
if (data->mcs.mod == MOD_NULL) {
mcs = data->mcs.mcs_idx;
} else {
@ -366,22 +366,22 @@ int dci_format1_pack(ra_pdsch_t *data, dci_msg_t *msg, uint8_t nof_prb) {
mcs = ra_mcs_to_table_idx(&data->mcs);
data->mcs.mcs_idx = mcs;
}
bit_pack(mcs, &y, 5);
bit_pack((uint32_t) mcs, &y, 5);
/* harq process number */
bit_pack(data->harq_process, &y, 3);
bit_pack((uint32_t) data->harq_process, &y, 3);
*y++ = data->ndi;
// rv version
bit_pack(data->rv_idx, &y, 2);
bit_pack((uint32_t) data->rv_idx, &y, 2);
// TPC not implemented
*y++ = 0;
*y++ = 0;
// Padding with zeros
int n = dci_format1_sizeof(nof_prb);
uint8_t n = dci_format1_sizeof(nof_prb);
while (y - msg->data < n) {
*y++ = 0;
}
@ -409,7 +409,7 @@ int dci_format1_unpack(dci_msg_t *msg, ra_pdsch_t *data, uint8_t nof_prb) {
/* Resource allocation: type0 or type 1 */
uint8_t P = ra_type0_P(nof_prb);
int alloc_size = (int) ceilf((float) nof_prb / P);
uint8_t alloc_size = (uint8_t) ceilf((float) nof_prb / P);
switch (data->alloc_type) {
case alloc_type0:
data->type0_alloc.rbg_bitmask = bit_unpack(&y, alloc_size);
@ -421,16 +421,24 @@ int dci_format1_unpack(dci_msg_t *msg, ra_pdsch_t *data, uint8_t nof_prb) {
alloc_size - (int) ceilf(log2f(P)) - 1);
break;
default:
fprintf(stderr,
"Format 1 accepts type0 or type1 resource allocation only\n");
fprintf(stderr, "Format 1 accepts type0 or type1 resource allocation only\n");
return LIBLTE_ERROR;
}
/* unpack MCS according to 7.1.7 of 36.213 */
uint32_t mcs = bit_unpack(&y, 5);
uint8_t mcs = bit_unpack(&y, 5);
data->mcs.mcs_idx = mcs;
ra_mcs_from_idx_dl(mcs, &data->mcs);
data->mcs.tbs = ra_tbs_from_idx(data->mcs.tbs_idx, ra_nprb_dl(data, nof_prb));
if (ra_mcs_from_idx_dl(mcs, &data->mcs)) {
fprintf(stderr, "Error getting MCS\n");
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 */
data->harq_process = bit_unpack(&y, 3);
@ -471,7 +479,7 @@ int dci_format1As_pack(ra_pdsch_t *data, dci_msg_t *msg, uint8_t nof_prb,
return LIBLTE_ERROR;
}
} else {
int n_vrb_dl;
uint8_t n_vrb_dl;
if (crc_is_crnti && nof_prb > 50) {
n_vrb_dl = 16;
} else {
@ -485,28 +493,28 @@ int dci_format1As_pack(ra_pdsch_t *data, dci_msg_t *msg, uint8_t nof_prb,
}
}
/* pack RIV according to 7.1.6.3 of 36.213 */
uint32_t riv;
uint16_t riv;
if (data->type2_alloc.L_crb) {
riv = ra_type2_to_riv(data->type2_alloc.L_crb, data->type2_alloc.RB_start,
nof_prb);
} else {
riv = data->type2_alloc.riv;
}
int nb_gap = 0;
uint8_t nb_gap = 0;
if (crc_is_crnti && data->type2_alloc.mode == t2_dist && nof_prb >= 50) {
nb_gap = 1;
*y++ = data->type2_alloc.n_gap;
}
bit_pack(riv, &y, riv_nbits(nof_prb) - nb_gap);
bit_pack((uint32_t) riv, &y, riv_nbits(nof_prb) - nb_gap);
// in format1A, MCS = TBS according to 7.1.7.2 of 36.213
uint32_t mcs;
uint8_t mcs;
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
int n_prb;
uint8_t n_prb;
if (!crc_is_crnti) {
n_prb = ra_nprb_dl(data, nof_prb);
} else {
@ -516,9 +524,9 @@ int dci_format1As_pack(ra_pdsch_t *data, dci_msg_t *msg, uint8_t nof_prb,
}
mcs = data->mcs.tbs_idx;
}
bit_pack(mcs, &y, 5);
bit_pack((uint32_t) mcs, &y, 5);
bit_pack(data->harq_process, &y, 3);
bit_pack((uint32_t) data->harq_process, &y, 3);
if (!crc_is_crnti && nof_prb >= 50 && data->type2_alloc.mode == t2_dist) {
*y++ = data->type2_alloc.n_gap;
@ -527,7 +535,7 @@ int dci_format1As_pack(ra_pdsch_t *data, dci_msg_t *msg, uint8_t nof_prb,
}
// rv version
bit_pack(data->rv_idx, &y, 2);
bit_pack((uint32_t) data->rv_idx, &y, 2);
if (crc_is_crnti) {
// TPC not implemented
@ -539,7 +547,7 @@ int dci_format1As_pack(ra_pdsch_t *data, dci_msg_t *msg, uint8_t nof_prb,
}
// Padding with zeros
int n = dci_format1A_sizeof(nof_prb);
uint8_t n = dci_format1A_sizeof(nof_prb);
while (y - msg->data < n) {
*y++ = 0;
}
@ -564,8 +572,7 @@ int dci_format1As_unpack(dci_msg_t *msg, ra_pdsch_t *data, uint8_t nof_prb,
}
if (*y++ != 1) {
fprintf(stderr,
"Invalid format differentiation field value. This is Format0\n");
fprintf(stderr, "Invalid format differentiation field value. This is Format0\n");
return LIBLTE_ERROR;
}
@ -576,18 +583,18 @@ int dci_format1As_unpack(dci_msg_t *msg, ra_pdsch_t *data, uint8_t nof_prb,
data->type2_alloc.n_gap = t2_ng1;
/* unpack RIV according to 7.1.6.3 of 36.213 */
int nb_gap = 0;
uint8_t nb_gap = 0;
if (crc_is_crnti && data->type2_alloc.mode == t2_dist && nof_prb >= 50) {
nb_gap = 1;
data->type2_alloc.n_gap = *y++;
}
int nof_vrb;
uint8_t nof_vrb;
if (data->type2_alloc.mode == t2_loc) {
nof_vrb = nof_prb;
} else {
nof_vrb = ra_type2_n_vrb_dl(nof_prb, data->type2_alloc.n_gap == t2_ng1);
}
uint32_t riv = bit_unpack(&y, riv_nbits(nof_prb) - nb_gap);
uint16_t riv = bit_unpack(&y, riv_nbits(nof_prb) - nb_gap);
ra_type2_from_riv(riv, &data->type2_alloc.L_crb, &data->type2_alloc.RB_start,
nof_prb, nof_vrb);
data->type2_alloc.riv = riv;
@ -604,7 +611,7 @@ int dci_format1As_unpack(dci_msg_t *msg, ra_pdsch_t *data, uint8_t nof_prb,
}
// rv version
bit_pack(data->rv_idx, &y, 2);
bit_pack((uint32_t) data->rv_idx, &y, 2);
if (crc_is_crnti) {
// TPC not implemented
@ -615,7 +622,8 @@ int dci_format1As_unpack(dci_msg_t *msg, ra_pdsch_t *data, uint8_t nof_prb,
data->type2_alloc.n_prb1a = *y++; // LSB indicates N_prb_1a for TBS
}
data->mcs.tbs_idx = data->mcs.mcs_idx;
int n_prb;
uint8_t n_prb;
if (crc_is_crnti) {
n_prb = ra_nprb_dl(data, nof_prb);
} else {
@ -644,13 +652,12 @@ int dci_format1Cs_pack(ra_pdsch_t *data, dci_msg_t *msg, uint8_t nof_prb) {
if (nof_prb >= 50) {
*y++ = data->type2_alloc.n_gap;
}
int n_step = ra_type2_n_rb_step(nof_prb);
int n_vrb_dl = ra_type2_n_vrb_dl(nof_prb, data->type2_alloc.n_gap == t2_ng1);
uint8_t n_step = ra_type2_n_rb_step(nof_prb);
uint8_t n_vrb_dl = ra_type2_n_vrb_dl(nof_prb, data->type2_alloc.n_gap == t2_ng1);
if (data->type2_alloc.L_crb > ((int) n_vrb_dl / n_step) * n_step) {
fprintf(stderr,
"L_CRB=%d can not exceed N_vrb_dl=%d for distributed type2\n",
data->type2_alloc.L_crb, ((int) n_vrb_dl / n_step) * n_step);
if (data->type2_alloc.L_crb > ((uint8_t) n_vrb_dl / n_step) * n_step) {
fprintf(stderr, "L_CRB=%d can not exceed N_vrb_dl=%d for distributed type2\n",
data->type2_alloc.L_crb, ((uint8_t) n_vrb_dl / n_step) * n_step);
return LIBLTE_ERROR;
}
if (data->type2_alloc.L_crb % n_step) {
@ -661,20 +668,20 @@ int dci_format1Cs_pack(ra_pdsch_t *data, dci_msg_t *msg, uint8_t nof_prb) {
fprintf(stderr, "RB_start must be multiple of n_step\n");
return LIBLTE_ERROR;
}
int L_p = data->type2_alloc.L_crb / n_step;
int RB_p = data->type2_alloc.RB_start / n_step;
int n_vrb_p = (int) n_vrb_dl / n_step;
uint8_t L_p = data->type2_alloc.L_crb / n_step;
uint8_t RB_p = data->type2_alloc.RB_start / n_step;
uint8_t n_vrb_p = (int) n_vrb_dl / n_step;
uint32_t riv;
uint16_t riv;
if (data->type2_alloc.L_crb) {
riv = ra_type2_to_riv(L_p, RB_p, n_vrb_p);
} else {
riv = data->type2_alloc.riv;
}
bit_pack(riv, &y, riv_nbits((int) n_vrb_dl / n_step));
bit_pack((uint32_t) riv, &y, riv_nbits((int) n_vrb_dl / n_step));
// in format1C, MCS = TBS according to 7.1.7.2 of 36.213
uint32_t mcs;
uint8_t mcs;
if (data->mcs.mod == MOD_NULL) {
mcs = data->mcs.mcs_idx;
} else {
@ -683,7 +690,7 @@ int dci_format1Cs_pack(ra_pdsch_t *data, dci_msg_t *msg, uint8_t nof_prb) {
}
mcs = data->mcs.tbs_idx;
}
bit_pack(mcs, &y, 5);
bit_pack((uint32_t) mcs, &y, 5);
msg->location.nof_bits = (y - msg->data);
@ -691,7 +698,7 @@ int dci_format1Cs_pack(ra_pdsch_t *data, dci_msg_t *msg, uint8_t nof_prb) {
}
int dci_format1Cs_unpack(dci_msg_t *msg, ra_pdsch_t *data, uint8_t nof_prb) {
uint16_t L_p, RB_p;
uint8_t L_p, RB_p;
/* pack bits */
char *y = msg->data;
@ -705,11 +712,11 @@ int dci_format1Cs_unpack(dci_msg_t *msg, ra_pdsch_t *data, uint8_t nof_prb) {
if (nof_prb >= 50) {
data->type2_alloc.n_gap = *y++;
}
int n_step = ra_type2_n_rb_step(nof_prb);
int n_vrb_dl = ra_type2_n_vrb_dl(nof_prb, data->type2_alloc.n_gap == t2_ng1);
uint8_t n_step = ra_type2_n_rb_step(nof_prb);
uint8_t n_vrb_dl = ra_type2_n_vrb_dl(nof_prb, data->type2_alloc.n_gap == t2_ng1);
uint32_t riv = bit_unpack(&y, riv_nbits((int) n_vrb_dl / n_step));
int n_vrb_p = (int) n_vrb_dl / n_step;
uint16_t riv = bit_unpack(&y, riv_nbits((int) n_vrb_dl / n_step));
uint8_t n_vrb_p = (uint8_t) n_vrb_dl / n_step;
ra_type2_from_riv(riv, &L_p, &RB_p, n_vrb_p, n_vrb_p);
data->type2_alloc.L_crb = L_p * n_step;
@ -800,7 +807,7 @@ void dci_msg_type_fprint(FILE *f, dci_msg_type_t type) {
}
int dci_msg_get_type(dci_msg_t *msg, dci_msg_type_t *type, uint8_t nof_prb,
unsigned short crnti) {
uint16_t crnti) {
if (msg->location.nof_bits == dci_format_sizeof(Format0, nof_prb)
&& !msg->data[0]) {
type->type = PUSCH_SCHED;

@ -50,47 +50,45 @@ bool pbch_exists(int nframe, int nslot) {
return (!(nframe % 5) && nslot == 1);
}
int pbch_cp(cf_t *input, cf_t *output, int nof_prb, lte_cp_t cp, int cell_id,
bool put) {
int pbch_cp(cf_t *input, cf_t *output, lte_cell_t cell, bool put) {
int i;
cf_t *ptr;
assert(cell_id >= 0);
if (put) {
ptr = input;
output += nof_prb * RE_X_RB / 2 - 36;
output += cell.nof_prb * RE_X_RB / 2 - 36;
} else {
ptr = output;
input += nof_prb * RE_X_RB / 2 - 36;
input += cell.nof_prb * RE_X_RB / 2 - 36;
}
/* symbol 0 & 1 */
for (i = 0; i < 2; i++) {
prb_cp_ref(&input, &output, cell_id % 3, 4, 4*6, put);
prb_cp_ref(&input, &output, cell.id % 3, 4, 4*6, put);
if (put) {
output += nof_prb * RE_X_RB - 2*36;
output += cell.nof_prb * RE_X_RB - 2*36;
} else {
input += nof_prb * RE_X_RB - 2*36;
input += cell.nof_prb * RE_X_RB - 2*36;
}
}
/* symbols 2 & 3 */
if (CP_ISNORM(cp)) {
if (CP_ISNORM(cell.cp)) {
for (i = 0; i < 2; i++) {
prb_cp(&input, &output, 6);
if (put) {
output += nof_prb * RE_X_RB - 2*36;
output += cell.nof_prb * RE_X_RB - 2*36;
} else {
input += nof_prb * RE_X_RB - 2*36;
input += cell.nof_prb * RE_X_RB - 2*36;
}
}
} else {
prb_cp(&input, &output, 6);
if (put) {
output += nof_prb * RE_X_RB - 2*36;
output += cell.nof_prb * RE_X_RB - 2*36;
} else {
input += nof_prb * RE_X_RB - 2*36;
input += cell.nof_prb * RE_X_RB - 2*36;
}
prb_cp_ref(&input, &output, cell_id % 3, 4, 4*6, put);
prb_cp_ref(&input, &output, cell.id % 3, 4, 4*6, put);
}
if (put) {
return input - ptr;
@ -106,9 +104,8 @@ int pbch_cp(cf_t *input, cf_t *output, int nof_prb, lte_cp_t cp, int cell_id,
*
* 36.211 10.3 section 6.6.4
*/
int pbch_put(cf_t *pbch, cf_t *slot1_data, int nof_prb, lte_cp_t cp,
int cell_id) {
return pbch_cp(pbch, slot1_data, nof_prb, cp, cell_id, true);
int pbch_put(cf_t *pbch, cf_t *slot1_data, lte_cell_t cell) {
return pbch_cp(pbch, slot1_data, cell, true);
}
/**
@ -118,21 +115,24 @@ int pbch_put(cf_t *pbch, cf_t *slot1_data, int nof_prb, lte_cp_t cp,
*
* 36.211 10.3 section 6.6.4
*/
int pbch_get(cf_t *slot1_data, cf_t *pbch, int nof_prb, lte_cp_t cp,
int cell_id) {
return pbch_cp(slot1_data, pbch, nof_prb, cp, cell_id, false);
int pbch_get(cf_t *slot1_data, cf_t *pbch, lte_cell_t cell) {
return pbch_cp(slot1_data, pbch, cell, false);
}
/** Initializes the PBCH transmitter and receiver */
int pbch_init(pbch_t *q, int nof_prb, int cell_id, lte_cp_t cp) {
int ret = -1;
if (cell_id < 0) {
return -1;
}
/** Initializes the PBCH transmitter and receiver.
* At the receiver, the field nof_ports in the cell structure indicates the
* maximum number of BS transmitter ports to look for.
*/
int pbch_init(pbch_t *q, lte_cell_t cell) {
int ret = LIBLTE_ERROR_INVALID_INPUTS;
if (q != NULL &&
lte_cell_isvalid(&cell))
{
ret = LIBLTE_ERROR;
bzero(q, sizeof(pbch_t));
q->cell_id = cell_id;
q->cp = cp;
q->nof_prb = nof_prb;
q->cell = cell;
if (modem_table_std(&q->mod, LTE_QPSK, true)) {
goto clean;
@ -140,7 +140,7 @@ int pbch_init(pbch_t *q, int nof_prb, int cell_id, lte_cp_t cp) {
demod_soft_init(&q->demod);
demod_soft_table_set(&q->demod, &q->mod);
demod_soft_alg_set(&q->demod, APPROX);
if (sequence_pbch(&q->seq_pbch, q->cp, q->cell_id)) {
if (sequence_pbch(&q->seq_pbch, q->cell.cp, q->cell.id)) {
goto clean;
}
@ -156,14 +156,14 @@ int pbch_init(pbch_t *q, int nof_prb, int cell_id, lte_cp_t cp) {
q->encoder.tail_biting = true;
memcpy(q->encoder.poly, poly, 3 * sizeof(int));
q->nof_symbols = (CP_ISNORM(q->cp)) ? PBCH_RE_CPNORM : PBCH_RE_CPEXT;
q->nof_symbols = (CP_ISNORM(q->cell.cp)) ? PBCH_RE_CPNORM : PBCH_RE_CPEXT;
q->pbch_d = malloc(sizeof(cf_t) * q->nof_symbols);
if (!q->pbch_d) {
goto clean;
}
int i;
for (i = 0; i < MAX_PORTS; i++) {
for (i = 0; i < q->cell.nof_ports; i++) {
q->ce[i] = malloc(sizeof(cf_t) * q->nof_symbols);
if (!q->ce[i]) {
goto clean;
@ -201,9 +201,10 @@ int pbch_init(pbch_t *q, int nof_prb, int cell_id, lte_cp_t cp) {
if (!q->data_enc) {
goto clean;
}
ret = 0;
clean: if (ret == -1) {
ret = LIBLTE_SUCCESS;
}
clean:
if (ret == LIBLTE_ERROR) {
pbch_free(q);
}
return ret;
@ -214,7 +215,7 @@ void pbch_free(pbch_t *q) {
free(q->pbch_d);
}
int i;
for (i = 0; i < MAX_PORTS; i++) {
for (i = 0; i < q->cell.nof_ports; i++) {
if (q->ce[i]) {
free(q->ce[i]);
}
@ -371,15 +372,15 @@ void crc_set_mask(char *data, int nof_ports) {
*
* Returns 0 if the data is correct, -1 otherwise
*/
int pbch_crc_check(pbch_t *q, char *bits, int nof_ports) {
uint32_t pbch_crc_check(pbch_t *q, char *bits, uint8_t nof_ports) {
char data[40];
memcpy(data, bits, 40 * sizeof(char));
crc_set_mask(data, nof_ports);
return crc_checksum(&q->crc, data, 40);
}
int pbch_decode_frame(pbch_t *q, pbch_mib_t *mib, int src, int dst, int n,
int nof_bits, int nof_ports) {
int pbch_decode_frame(pbch_t *q, pbch_mib_t *mib, uint8_t src, uint8_t dst, uint8_t n,
uint16_t nof_bits, uint8_t nof_ports) {
int j;
memcpy(&q->temp[dst * nof_bits], &q->pbch_llr[src * nof_bits],
@ -433,20 +434,38 @@ int pbch_decode_frame(pbch_t *q, pbch_mib_t *mib, int src, int dst, int n,
/* Decodes the PBCH channel
*
* The PBCH spans in 40 ms. This function is called every 10 ms. It tries to decode the MIB
* given the symbols of the slot #1 of each radio frame. Successive calls will use more frames
* given the symbols of a subframe (1 ms). Successive calls will use more subframes
* to help the decoding process.
*
* Returns 1 if successfully decoded MIB, 0 if not and -1 on error
*/
int pbch_decode(pbch_t *q, cf_t *slot1_symbols, cf_t *ce[MAX_PORTS], pbch_mib_t *mib) {
int src, dst, res, nb;
int nant_[3] = { 1, 2, 4 };
int na, nant;
/* Set pointers for layermapping & precoding */
int pbch_decode(pbch_t *q, cf_t *sf_symbols, cf_t *ce[MAX_PORTS], pbch_mib_t *mib) {
uint8_t src, dst, nb;
uint8_t nant_[3] = { 1, 2, 4 };
uint8_t na, nant;
cf_t *slot1_symbols;
int i;
int nof_bits = 2 * q->nof_symbols;
int nof_bits;
cf_t *x[MAX_LAYERS];
cf_t *ce_slot[MAX_PORTS];
int ret = LIBLTE_ERROR_INVALID_INPUTS;
if (q != NULL &&
sf_symbols != NULL &&
mib != NULL)
{
for (i=0;i<q->cell.nof_ports;i++) {
if (ce[i] == NULL) {
return LIBLTE_ERROR_INVALID_INPUTS;
} else {
ce_slot[i] = &ce[i][q->cell.nof_prb * RE_X_RB * CP_NSYMB(q->cell.cp)];
}
}
slot1_symbols = &sf_symbols[q->cell.nof_prb * RE_X_RB * CP_NSYMB(q->cell.cp)];
/* Set pointers for layermapping & precoding */
nof_bits = 2 * q->nof_symbols;
/* number of layers equals number of ports */
for (i = 0; i < MAX_PORTS; i++) {
@ -455,27 +474,24 @@ int pbch_decode(pbch_t *q, cf_t *slot1_symbols, cf_t *ce[MAX_PORTS], pbch_mib_t
memset(&x[MAX_PORTS], 0, sizeof(cf_t*) * (MAX_LAYERS - MAX_PORTS));
/* extract symbols */
if (q->nof_symbols
!= pbch_get(slot1_symbols, q->pbch_symbols[0], q->nof_prb, q->cp,
q->cell_id)) {
if (q->nof_symbols != pbch_get(slot1_symbols, q->pbch_symbols[0], q->cell)) {
fprintf(stderr, "There was an error getting the PBCH symbols\n");
return -1;
return LIBLTE_ERROR;
}
/* extract channel estimates */
for (i = 0; i < MAX_PORTS; i++) {
if (q->nof_symbols
!= pbch_get(ce[i], q->ce[i], q->nof_prb, q->cp, q->cell_id)) {
for (i = 0; i < q->cell.nof_ports; i++) {
if (q->nof_symbols != pbch_get(ce_slot[i], q->ce[i], q->cell)) {
fprintf(stderr, "There was an error getting the PBCH symbols\n");
return -1;
return LIBLTE_ERROR;
}
}
q->frame_idx++;
res = 0;
ret = 0;
/* Try decoding for 1 to 4 antennas */
for (na = 0; na < 3 && !res; na++) {
/* Try decoding for 1 to cell.nof_ports antennas */
for (na = 0; na < q->cell.nof_ports && !ret; na++) {
nant = nant_[na];
INFO("Trying %d TX antennas with %d frames\n", nant, q->frame_idx);
@ -503,12 +519,13 @@ int pbch_decode(pbch_t *q, cf_t *slot1_symbols, cf_t *ce[MAX_PORTS], pbch_mib_t
* FIXME: There are unnecessary checks because 2,3,4 have already been processed in the previous
* calls.
*/
for (nb = 0; nb < q->frame_idx && !res; nb++) {
for (dst = 0; (dst < 4 - nb) && !res; dst++) {
for (src = 0; src < q->frame_idx - nb && !res; src++) {
for (nb = 0; nb < q->frame_idx && !ret; nb++) {
for (dst = 0; (dst < 4 - nb) && !ret; dst++) {
for (src = 0; src < q->frame_idx - nb && !ret; src++) {
DEBUG("Trying %d blocks at offset %d as subframe mod4 number %d\n",
nb + 1, src, dst);
res = pbch_decode_frame(q, mib, src, dst, nb + 1, nof_bits, nant);
ret = pbch_decode_frame(q, mib, src, dst, nb + 1, nof_bits, nant);
}
}
}
@ -519,26 +536,36 @@ int pbch_decode(pbch_t *q, cf_t *slot1_symbols, cf_t *ce[MAX_PORTS], pbch_mib_t
memmove(q->pbch_llr, &q->pbch_llr[nof_bits], nof_bits * 3 * sizeof(float));
q->frame_idx = 3;
}
return res;
}
return ret;
}
/** Converts the MIB message to symbols mapped to SLOT #1 ready for transmission
*/
void pbch_encode(pbch_t *q, pbch_mib_t *mib,
cf_t *slot1_symbols[MAX_PORTS], int nof_ports) {
int pbch_encode(pbch_t *q, pbch_mib_t *mib, cf_t *sf_symbols[MAX_PORTS]) {
int i;
int nof_bits = 2 * q->nof_symbols;
assert(nof_ports <= MAX_PORTS);
int nof_bits;
cf_t *slot1_symbols[MAX_PORTS];
cf_t *x[MAX_LAYERS];
if (q != NULL &&
mib != NULL)
{
for (i=0;i<q->cell.nof_ports;i++) {
if (sf_symbols[i] == NULL) {
return LIBLTE_ERROR_INVALID_INPUTS;
} else {
slot1_symbols[i] = &sf_symbols[i][q->cell.nof_prb * RE_X_RB * CP_NSYMB(q->cell.cp)];
}
}
/* Set pointers for layermapping & precoding */
cf_t *x[MAX_LAYERS];
nof_bits = 2 * q->nof_symbols;
/* number of layers equals number of ports */
for (i = 0; i < nof_ports; i++) {
for (i = 0; i < q->cell.nof_ports; i++) {
x[i] = q->pbch_x[i];
}
memset(&x[nof_ports], 0, sizeof(cf_t*) * (MAX_LAYERS - nof_ports));
memset(&x[q->cell.nof_ports], 0, sizeof(cf_t*) * (MAX_LAYERS - q->cell.nof_ports));
if (q->frame_idx == 0) {
/* pack MIB */
@ -546,7 +573,7 @@ void pbch_encode(pbch_t *q, pbch_mib_t *mib,
/* encode & modulate */
crc_attach(&q->crc, q->data, 24);
crc_set_mask(q->data, nof_ports);
crc_set_mask(q->data, q->cell.nof_ports);
convcoder_encode(&q->encoder, q->data, q->data_enc, 40);
@ -560,22 +587,25 @@ void pbch_encode(pbch_t *q, pbch_mib_t *mib,
nof_bits);
/* layer mapping & precoding */
if (nof_ports > 1) {
layermap_diversity(q->pbch_d, x, nof_ports, q->nof_symbols);
precoding_diversity(x, q->pbch_symbols, nof_ports,
q->nof_symbols / nof_ports);
if (q->cell.nof_ports > 1) {
layermap_diversity(q->pbch_d, x, q->cell.nof_ports, q->nof_symbols);
precoding_diversity(x, q->pbch_symbols, q->cell.nof_ports,
q->nof_symbols / q->cell.nof_ports);
} else {
memcpy(q->pbch_symbols[0], q->pbch_d, q->nof_symbols * sizeof(cf_t));
}
/* mapping to resource elements */
for (i = 0; i < nof_ports; i++) {
pbch_put(q->pbch_symbols[i], slot1_symbols[i], q->nof_prb, q->cp,
q->cell_id);
for (i = 0; i < q->cell.nof_ports; i++) {
pbch_put(q->pbch_symbols[i], slot1_symbols[i], q->cell);
}
q->frame_idx++;
if (q->frame_idx == 4) {
q->frame_idx = 0;
}
return LIBLTE_SUCCESS;
} else {
return LIBLTE_ERROR_INVALID_INPUTS;
}
}

@ -61,10 +61,10 @@ struct cb_segm {
int pdsch_cp(pdsch_t *q, cf_t *input, cf_t *output, ra_prb_t *prb_alloc,
uint8_t nsubframe, bool put) {
int s, n, l, lp, lstart, lend, nof_refs;
uint8_t s, n, l, lp, lstart, lend, nof_refs;
bool is_pbch, is_sss;
cf_t *in_ptr = input, *out_ptr = output;
int offset;
uint8_t offset;
INFO("%s %d RE from %d PRB\n", put ? "Putting" : "Getting",
prb_alloc->re_sf[nsubframe], prb_alloc->slot[0].nof_prb);
@ -76,7 +76,6 @@ int pdsch_cp(pdsch_t *q, cf_t *input, cf_t *output, ra_prb_t *prb_alloc,
}
for (s = 0; s < 2; s++) {
for (l = 0; l < CP_NSYMB(q->cell.cp); l++) {
for (n = 0; n < prb_alloc->slot[s].nof_prb; n++) {
if (s == 0) {

@ -41,23 +41,23 @@
#define min(a,b) (a<b?a:b)
/* Returns the number of RE in a PRB in a slot and subframe */
int ra_re_x_prb(int nsubframe, int nslot, int prb_idx, int nof_prb,
int nof_ports, int nof_ctrl_symbols, lte_cp_t cp) {
uint16_t ra_re_x_prb(uint8_t subframe, uint8_t slot, uint8_t prb_idx, uint8_t nof_prb,
uint8_t nof_ports, uint8_t nof_ctrl_symbols, lte_cp_t cp) {
int re;
uint16_t re;
bool skip_refs = false;
if (nslot == 0) {
if (slot == 0) {
re = (CP_NSYMB(cp) - nof_ctrl_symbols) * RE_X_RB;
} else {
re = CP_NSYMB(cp) * RE_X_RB;
}
/* if it's the prb in the middle, there are less RE due to PBCH and PSS/SSS */
if ((nsubframe == 0 || nsubframe == 5)
if ((subframe == 0 || subframe == 5)
&& (prb_idx >= nof_prb / 2 - 3 && prb_idx <= nof_prb / 2 + 3)) {
if (nsubframe == 0) {
if (nslot == 0) {
if (subframe == 0) {
if (slot == 0) {
re = (CP_NSYMB(cp) - nof_ctrl_symbols - 2) * RE_X_RB;
} else {
if (CP_ISEXT(cp)) {
@ -67,16 +67,16 @@ int ra_re_x_prb(int nsubframe, int nslot, int prb_idx, int nof_prb,
re = (CP_NSYMB(cp) - 4) * RE_X_RB + 2 * nof_ports;
}
}
} else if (nsubframe == 5) {
if (nslot == 0) {
} else if (subframe == 5) {
if (slot == 0) {
re = (CP_NSYMB(cp) - nof_ctrl_symbols - 2) * RE_X_RB;
}
}
if ((nof_prb % 2)
&& (prb_idx == nof_prb / 2 - 3 || prb_idx == nof_prb / 2 + 3)) {
if (nslot == 0) {
if (slot == 0) {
re += 2 * RE_X_RB / 2;
} else if (nsubframe == 0) {
} else if (subframe == 0) {
re += 4 * RE_X_RB / 2 - nof_ports;
if (CP_ISEXT(cp)) {
re -= nof_ports > 2 ? 2 : nof_ports;
@ -90,10 +90,10 @@ int ra_re_x_prb(int nsubframe, int nslot, int prb_idx, int nof_prb,
switch (nof_ports) {
case 1:
case 2:
re -= 2 * (nslot + 1) * nof_ports;
re -= 2 * (slot + 1) * nof_ports;
break;
case 4:
if (nslot == 1) {
if (slot == 1) {
re -= 12;
} else {
re -= 4;
@ -109,9 +109,9 @@ int ra_re_x_prb(int nsubframe, int nslot, int prb_idx, int nof_prb,
}
/* Computes the number of RE for each PRB in the prb_dist structure */
void ra_prb_get_re(ra_prb_t *prb_dist, int nof_prb, int nof_ports,
int nof_ctrl_symbols, lte_cp_t cp) {
int i, j, s;
void ra_prb_get_re_dl(ra_prb_t *prb_dist, uint8_t nof_prb, uint8_t nof_ports,
uint8_t nof_ctrl_symbols, lte_cp_t cp) {
uint8_t i, j, s;
/* Set start symbol according to Section 7.1.6.4 in 36.213 */
prb_dist->lstart = nof_ctrl_symbols;
@ -139,25 +139,25 @@ void ra_prb_fprint(FILE *f, ra_prb_slot_t *prb) {
}
/** 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 ra_prb_get_ul(ra_prb_slot_t *prb, ra_pusch_t *ra, uint8_t nof_prb) {
int i;
if (ra->type2_alloc.mode != t2_loc) {
fprintf(stderr, "Uplink only accepts type2 localized scheduling\n");
return -1;
return LIBLTE_ERROR;
}
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;
return LIBLTE_SUCCESS;
}
/** 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 ra_prb_get_dl(ra_prb_t *prb_dist, ra_pdsch_t *ra, uint8_t nof_prb) {
int i, j;
uint32_t bitmask;
int P = ra_type0_P(nof_prb);
int n_rb_rbg_subset, n_rb_type1;
uint8_t P = ra_type0_P(nof_prb);
uint8_t n_rb_rbg_subset, n_rb_type1;
bzero(prb_dist, sizeof(ra_prb_t));
switch (ra->alloc_type) {
@ -260,33 +260,33 @@ int ra_prb_get_dl(ra_prb_t *prb_dist, ra_pdsch_t *ra, int nof_prb) {
}
break;
default:
return -1;
return LIBLTE_ERROR;
}
return 0;
return LIBLTE_SUCCESS;
}
/* Returns the number of allocated PRB for Uplink */
int ra_nprb_ul(ra_pusch_t *ra, int nof_prb) {
uint16_t ra_nprb_ul(ra_pusch_t *ra, uint8_t 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;
uint16_t ra_nprb_dl(ra_pdsch_t *ra, uint8_t nof_prb) {
uint8_t nprb;
uint8_t 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)) {
nof_rbg = (int) ceilf((float) nof_prb / P) - 1;
if (nof_rbg > (uint8_t) ceilf((float) nof_prb / P)) {
nof_rbg = (uint8_t) ceilf((float) nof_prb / P) - 1;
}
nprb = nof_rbg * P;
// last RBG may have smaller size. Add if set
int P_last = (nof_prb % P);
uint8_t P_last = (nof_prb % P);
if (!P_last)
P_last = P;
nprb += P_last * (ra->type0_alloc.rbg_bitmask & 1);
@ -296,20 +296,20 @@ int ra_nprb_dl(ra_pdsch_t *ra, int nof_prb) {
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;
return LIBLTE_ERROR;
}
break;
case alloc_type2:
nprb = ra->type2_alloc.L_crb;
break;
default:
return -1;
return LIBLTE_ERROR;
}
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) {
uint8_t ra_type0_P(uint8_t nof_prb) {
if (nof_prb <= 10) {
return 1;
} else if (nof_prb <= 26) {
@ -322,15 +322,15 @@ int ra_type0_P(int nof_prb) {
}
/* 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;
uint8_t ra_type1_N_rb(uint8_t nof_prb) {
uint8_t P = ra_type0_P(nof_prb);
return (uint8_t) ceilf((float) nof_prb / P) - (uint8_t) 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) {
uint16_t ra_type2_to_riv(uint8_t L_crb, uint8_t RB_start, uint8_t nof_prb) {
uint16_t riv;
if (L_crb <= 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;
@ -339,10 +339,10 @@ uint32_t ra_type2_to_riv(uint16_t L_crb, uint16_t RB_start, int nof_prb) {
}
/* 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;
void ra_type2_from_riv(uint16_t riv, uint8_t *L_crb, uint8_t *RB_start,
uint8_t nof_prb, uint8_t nof_vrb) {
*L_crb = (uint8_t) (riv / nof_prb) + 1;
*RB_start = (uint8_t) (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;
@ -350,7 +350,7 @@ void ra_type2_from_riv(uint32_t riv, uint16_t *L_crb, uint16_t *RB_start,
}
/* Table 6.2.3.2-1 in 36.211 */
int ra_type2_ngap(int nof_prb, bool ngap_is_1) {
uint8_t ra_type2_ngap(uint8_t nof_prb, bool ngap_is_1) {
if (nof_prb <= 10) {
return nof_prb / 2;
} else if (nof_prb == 11) {
@ -373,7 +373,7 @@ int ra_type2_ngap(int nof_prb, bool ngap_is_1) {
}
/* Table 7.1.6.3-1 in 36.213 */
int ra_type2_n_rb_step(int nof_prb) {
uint8_t ra_type2_n_rb_step(uint8_t nof_prb) {
if (nof_prb < 50) {
return 2;
} else {
@ -382,12 +382,12 @@ int ra_type2_n_rb_step(int nof_prb) {
}
/* 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);
uint8_t ra_type2_n_vrb_dl(uint8_t nof_prb, bool ngap_is_1) {
uint8_t 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;
return ((uint8_t) nof_prb / ngap) * 2 * ngap;
}
}
@ -401,7 +401,7 @@ uint8_t ra_mcs_to_table_idx(ra_mcs_t *mcs) {
case QAM64:
return mcs->tbs_idx + 2;
default:
return 0;
return LIBLTE_SUCCESS;
}
}
@ -428,9 +428,9 @@ int ra_mcs_from_idx_dl(uint8_t idx, ra_mcs_t *mcs) {
} else {
mcs->mod = MOD_NULL;
mcs->tbs_idx = 0;
return -1;
return LIBLTE_ERROR;
}
return 0;
return LIBLTE_SUCCESS;
}
/* Converts MCS index to ra_mcs_t structure for Uplink as defined in Table 8.6.1-1 on 36.213 */
@ -447,9 +447,9 @@ int ra_mcs_from_idx_ul(uint8_t idx, ra_mcs_t *mcs) {
} else {
mcs->mod = MOD_NULL;
mcs->tbs_idx = 0;
return -1;
return LIBLTE_ERROR;
}
return 0;
return LIBLTE_SUCCESS;
}
/* Downlink Transport Block size for Format 1C as defined in 7.1.7.2.2-1 on 36.213 */
@ -457,52 +457,52 @@ int ra_tbs_from_idx_format1c(uint8_t tbs_idx) {
if (tbs_idx < 32) {
return tbs_format1c_table[tbs_idx];
} else {
return -1;
return LIBLTE_ERROR;
}
}
/* 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 ra_tbs_to_table_idx_format1c(uint32_t tbs) {
int idx;
if (tbs < tbs_format1c_table[0]) {
return -1;
return LIBLTE_ERROR;
}
for (idx = 1; idx < 32; idx++) {
if (tbs_format1c_table[idx - 1] <= tbs && tbs_format1c_table[idx] >= tbs) {
return idx;
}
}
return -1;
return LIBLTE_ERROR;
}
/* 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) {
int ra_tbs_from_idx(uint8_t tbs_idx, uint8_t n_prb) {
if (tbs_idx < 27 && n_prb > 0 && n_prb <= MAX_PRB) {
return tbs_table[tbs_idx][n_prb - 1];
} else {
return -1;
return LIBLTE_ERROR;
}
}
/* 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 ra_tbs_to_table_idx(uint32_t tbs, uint8_t n_prb) {
int idx;
if (n_prb > 0 && n_prb <= 110) {
return -1;
if (n_prb > 0 && n_prb <= MAX_PRB) {
return LIBLTE_ERROR;
}
if (tbs < tbs_table[0][n_prb]) {
return -1;
return LIBLTE_ERROR;
}
for (idx = 1; idx < 28; idx++) {
if (tbs_table[idx - 1][n_prb] <= tbs && tbs_table[idx][n_prb] >= tbs) {
return idx;
}
}
return -1;
return LIBLTE_ERROR;
}
char *ra_mod_string(ra_mod_t mod) {
@ -518,7 +518,7 @@ char *ra_mod_string(ra_mod_t mod) {
}
}
void ra_pusch_fprint(FILE *f, ra_pusch_t *ra, int nof_prb) {
void ra_pusch_fprint(FILE *f, ra_pusch_t *ra, uint8_t nof_prb) {
fprintf(f, "Frequency Hopping:\t");
if (ra->freq_hop_fl == hop_disabled) {
fprintf(f, "No");
@ -551,7 +551,7 @@ void ra_pdsch_set_mcs(ra_pdsch_t *ra, ra_mod_t mod, uint8_t tbs_idx) {
ra->mcs.tbs = 0;
}
void ra_pdsch_fprint(FILE *f, ra_pdsch_t *ra, int nof_prb) {
void ra_pdsch_fprint(FILE *f, ra_pdsch_t *ra, uint8_t nof_prb) {
fprintf(f, " - Resource Allocation Type:\t\t%s\n",
ra_type_string(ra->alloc_type));
switch (ra->alloc_type) {

@ -117,14 +117,14 @@ int base_init() {
exit(-1);
}
fft_buffer = malloc(CP_NSYMB(cell.cp) * cell.nof_prb * RE_X_RB * sizeof(cf_t));
fft_buffer = malloc(2 * CP_NSYMB(cell.cp) * cell.nof_prb * RE_X_RB * sizeof(cf_t));
if (!fft_buffer) {
perror("malloc");
return -1;
}
for (i=0;i<MAX_PORTS;i++) {
ce[i] = malloc(CP_NSYMB(cell.cp) * cell.nof_prb * RE_X_RB * sizeof(cf_t));
for (i=0;i<cell.nof_ports;i++) {
ce[i] = malloc(2 * CP_NSYMB(cell.cp) * cell.nof_prb * RE_X_RB * sizeof(cf_t));
if (!ce[i]) {
perror("malloc");
return -1;
@ -146,7 +146,7 @@ int base_init() {
return -1;
}
if (pbch_init(&pbch, cell.nof_prb, cell.id, cell.cp)) {
if (pbch_init(&pbch, cell)) {
fprintf(stderr, "Error initiating PBCH\n");
return -1;
}
@ -167,7 +167,7 @@ void base_free() {
free(fft_buffer);
filesource_free(&fsrc);
for (i=0;i<MAX_PORTS;i++) {
for (i=0;i<cell.nof_ports;i++) {
free(ce[i]);
}
chest_free(&chest);
@ -178,7 +178,7 @@ void base_free() {
int main(int argc, char **argv) {
pbch_mib_t mib;
int i, n;
int n;
if (argc < 3) {
usage(argv[0]);
@ -194,7 +194,7 @@ int main(int argc, char **argv) {
n = filesource_read(&fsrc, input_buffer, FLEN);
lte_fft_run_slot(&fft, &input_buffer[960], fft_buffer);
lte_fft_run_sf(&fft, input_buffer, fft_buffer);
if (fmatlab) {
fprintf(fmatlab, "outfft=");
@ -205,12 +205,7 @@ int main(int argc, char **argv) {
}
/* Get channel estimates for each port */
for (i=0;i<cell.nof_ports;i++) {
chest_ce_slot_port(&chest, fft_buffer, ce[i], 1, i);
if (fmatlab) {
chest_fprint(&chest, fmatlab, 1, i);
}
}
chest_ce_sf(&chest, fft_buffer, ce, 0);
INFO("Decoding PBCH\n", 0);

@ -33,16 +33,18 @@
#include "liblte/phy/phy.h"
int cell_id = 1;
int nof_prb = 6;
int nof_ports = 1;
lte_cell_t cell = {
6, // nof_prb
1, // nof_ports
1, // cell_id
CPNORM // cyclic prefix
};
void usage(char *prog) {
printf("Usage: %s [cpv]\n", prog);
printf("\t-c cell id [Default %d]\n", cell_id);
printf("\t-p nof_ports [Default %d]\n", nof_ports);
printf("\t-n nof_prb [Default %d]\n", nof_prb);
printf("\t-c cell id [Default %d]\n", cell.id);
printf("\t-p cell.nof_ports [Default %d]\n", cell.nof_ports);
printf("\t-n cell.nof_prb [Default %d]\n", cell.nof_prb);
printf("\t-v [set verbose to debug, default none]\n");
}
@ -51,13 +53,13 @@ void parse_args(int argc, char **argv) {
while ((opt = getopt(argc, argv, "cpnv")) != -1) {
switch(opt) {
case 'p':
nof_ports = atoi(argv[optind]);
cell.nof_ports = atoi(argv[optind]);
break;
case 'n':
nof_prb = atoi(argv[optind]);
cell.nof_prb = atoi(argv[optind]);
break;
case 'c':
cell_id = atoi(argv[optind]);
cell.id = atoi(argv[optind]);
break;
case 'v':
verbose++;
@ -76,14 +78,14 @@ int main(int argc, char **argv) {
int i, j;
cf_t *ce[MAX_PORTS];
int nof_re;
cf_t *slot1_symbols[MAX_PORTS];
cf_t *sf_symbols[MAX_PORTS];
parse_args(argc,argv);
nof_re = CPNORM_NSYMB * nof_prb * RE_X_RB;
nof_re = 2 * CPNORM_NSYMB * cell.nof_prb * RE_X_RB;
/* init memory */
for (i=0;i<MAX_PORTS;i++) {
for (i=0;i<cell.nof_ports;i++) {
ce[i] = malloc(sizeof(cf_t) * nof_re);
if (!ce[i]) {
perror("malloc");
@ -92,44 +94,44 @@ int main(int argc, char **argv) {
for (j=0;j<nof_re;j++) {
ce[i][j] = 1;
}
slot1_symbols[i] = malloc(sizeof(cf_t) * nof_re);
if (!slot1_symbols[i]) {
sf_symbols[i] = malloc(sizeof(cf_t) * nof_re);
if (!sf_symbols[i]) {
perror("malloc");
exit(-1);
}
}
if (pbch_init(&pbch, nof_prb, cell_id, CPNORM)) {
if (pbch_init(&pbch, cell)) {
fprintf(stderr, "Error creating PBCH object\n");
exit(-1);
}
mib_tx.nof_ports = nof_ports;
mib_tx.nof_ports = cell.nof_ports;
mib_tx.nof_prb = 50;
mib_tx.phich_length = PHICH_EXT;
mib_tx.phich_resources = R_1_6;
mib_tx.sfn = 124;
pbch_encode(&pbch, &mib_tx, slot1_symbols, nof_ports);
pbch_encode(&pbch, &mib_tx, sf_symbols);
/* combine outputs */
for (i=1;i<nof_ports;i++) {
for (i=1;i<cell.nof_ports;i++) {
for (j=0;j<nof_re;j++) {
slot1_symbols[0][j] += slot1_symbols[i][j];
sf_symbols[0][j] += sf_symbols[i][j];
}
}
pbch_decode_reset(&pbch);
if (1 != pbch_decode(&pbch, slot1_symbols[0], ce, &mib_rx)) {
if (1 != pbch_decode(&pbch, sf_symbols[0], ce, &mib_rx)) {
printf("Error decoding\n");
exit(-1);
}
pbch_free(&pbch);
for (i=0;i<MAX_PORTS;i++) {
for (i=0;i<cell.nof_ports;i++) {
free(ce[i]);
free(slot1_symbols[i]);
free(sf_symbols[i]);
}
if (!memcmp(&mib_tx, &mib_rx, sizeof(pbch_mib_t))) {

@ -314,7 +314,7 @@ int main(int argc, char **argv) {
fprintf(stderr, "Error computing resource allocation\n");
goto goout;
}
ra_prb_get_re(&prb_alloc, cell.nof_prb, cell.nof_ports, cell.nof_prb<10?(cfi+1):cfi, cell.cp);
ra_prb_get_re_dl(&prb_alloc, cell.nof_prb, cell.nof_ports, cell.nof_prb<10?(cfi+1):cfi, cell.cp);
if (pdsch_decode(&pdsch, fft_buffer, ce, data, nof_frames%10, ra_dl.mcs, &prb_alloc)) {
fprintf(stderr, "Error decoding PDSCH\n");

@ -80,10 +80,10 @@ int main(int argc, char **argv) {
pdsch_init(&pdsch, 0, cell);
memset(prb_alloc.re_sf, 0, sizeof(int) * 10);
memset(prb_alloc.re_sf, 0, sizeof(uint16_t) * 10);
prb_alloc.slot[0].nof_prb = test_re_prb[i];
prb_alloc.slot[1].nof_prb = test_re_prb[i];
ra_prb_get_re(&prb_alloc, test_re_prb[i], test_re_ports[i], test_re_csymb[i], test_re_cp[i]);
ra_prb_get_re_dl(&prb_alloc, test_re_prb[i], test_re_ports[i], test_re_csymb[i], test_re_cp[i]);
for (n=0;n<10;n++) {
switch(n) {
case 0:

@ -134,7 +134,7 @@ int main(int argc, char **argv) {
}
memcpy(&prb_alloc.slot[1], &prb_alloc.slot[0], sizeof(ra_prb_slot_t));
ra_prb_get_re(&prb_alloc, cell.nof_prb, cell.nof_ports, 2, CPNORM);
ra_prb_get_re_dl(&prb_alloc, cell.nof_prb, cell.nof_ports, 2, CPNORM);
/* init memory */
for (i=0;i<cell.nof_ports;i++) {

@ -75,7 +75,7 @@ unsigned int bit_diff(char *x, char *y, int nbits) {
}
// Counts the number of ones in a word. K&R book exercise 2.9
int bit_count(unsigned int n) {
uint8_t bit_count(uint32_t n) {
int c;
for (c = 0; n; c++)
n &= n - 1;

Loading…
Cancel
Save