diff --git a/CMakeLists.txt b/CMakeLists.txt index 17609e65f..2f020db8f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -95,6 +95,8 @@ else(POLARSSL_FOUND) set(SEC_LIBRARIES "${MBEDTLS_LIBRARIES}") endif(BUILD_STATIC) add_definitions(-DHAVE_MBEDTLS) + else(MBEDTLS_FOUND) + message(FATAL_ERROR "Either PolarSSL or mbedTLS are required to build srsLTE") endif (MBEDTLS_FOUND) endif(POLARSSL_FOUND) diff --git a/cmake/modules/FindMbedTLS.cmake b/cmake/modules/FindMbedTLS.cmake index 11499bad4..2c9464e79 100644 --- a/cmake/modules/FindMbedTLS.cmake +++ b/cmake/modules/FindMbedTLS.cmake @@ -50,5 +50,5 @@ message(STATUS "MBEDTLS STATIC LIBRARIES: " ${MBEDTLS_STATIC_LIBRARIES}) message(STATUS "MBEDTLS INCLUDE DIRS: " ${MBEDTLS_INCLUDE_DIRS}) INCLUDE(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(MBEDTLS DEFAULT_MSG MBEDTLS_LIBRARIES MBEDTLS_STATIC_LIBRARIES MBEDTLS_INCLUDE_DIRS) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(MBEDTLS DEFAULT_MSG MBEDTLS_LIBRARIES MBEDTLS_INCLUDE_DIRS) MARK_AS_ADVANCED(MBEDTLS_LIBRARIES MBEDTLS_STATIC_LIBRARIES MBEDTLS_INCLUDE_DIRS) diff --git a/lib/examples/cell_measurement.c b/lib/examples/cell_measurement.c index bc8262b29..96e98f055 100644 --- a/lib/examples/cell_measurement.c +++ b/lib/examples/cell_measurement.c @@ -237,19 +237,31 @@ int main(int argc, char **argv) { srslte_rf_stop_rx_stream(&rf); srslte_rf_flush_buffer(&rf); - if (srslte_ue_sync_init_multi(&ue_sync, cell, srslte_rf_recv_wrapper, 1, (void*) &rf)) { + if (srslte_ue_sync_init_multi(&ue_sync, cell.nof_prb, cell.id==1000, srslte_rf_recv_wrapper, 1, (void*) &rf)) { fprintf(stderr, "Error initiating ue_sync\n"); return -1; } - if (srslte_ue_dl_init_multi(&ue_dl, cell, 1)) { + if (srslte_ue_sync_set_cell(&ue_sync, cell)) { + fprintf(stderr, "Error initiating ue_sync\n"); + return -1; + } + if (srslte_ue_dl_init_multi(&ue_dl, cell.nof_prb, 1)) { fprintf(stderr, "Error initiating UE downlink processing module\n"); return -1; } - if (srslte_ue_mib_init(&ue_mib, cell)) { + if (srslte_ue_dl_set_cell(&ue_dl, cell)) { + fprintf(stderr, "Error initiating UE downlink processing module\n"); + return -1; + } + if (srslte_ue_mib_init(&ue_mib, cell.nof_prb)) { fprintf(stderr, "Error initaiting UE MIB decoder\n"); return -1; } - + if (srslte_ue_mib_set_cell(&ue_mib, cell)) { + fprintf(stderr, "Error initaiting UE MIB decoder\n"); + return -1; + } + /* Configure downlink receiver for the SI-RNTI since will be the only one we'll use */ srslte_ue_dl_set_rnti(&ue_dl, SRSLTE_SIRNTI); @@ -260,11 +272,15 @@ int main(int argc, char **argv) { fprintf(stderr, "Error initiating FFT\n"); return -1; } - if (srslte_chest_dl_init(&chest, cell)) { + if (srslte_chest_dl_init(&chest, cell.nof_prb)) { fprintf(stderr, "Error initiating channel estimator\n"); return -1; } - + if (srslte_chest_dl_set_cell(&chest, cell)) { + fprintf(stderr, "Error initiating channel estimator\n"); + return -1; + } + int sf_re = SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp); cf_t *sf_symbols = srslte_vec_malloc(sf_re * sizeof(cf_t)); diff --git a/lib/examples/cell_search.c b/lib/examples/cell_search.c index 8ab560e0c..281e3d102 100644 --- a/lib/examples/cell_search.c +++ b/lib/examples/cell_search.c @@ -188,6 +188,18 @@ int main(int argc, char **argv) { sigprocmask(SIG_UNBLOCK, &sigset, NULL); signal(SIGINT, sig_int_handler); + if (srslte_ue_cellsearch_init_multi(&cs, cell_detect_config.max_frames_pss, srslte_rf_recv_wrapper, 1, (void*) &rf)) { + fprintf(stderr, "Error initiating UE cell detect\n"); + exit(-1); + } + + if (cell_detect_config.max_frames_pss) { + srslte_ue_cellsearch_set_nof_valid_frames(&cs, cell_detect_config.nof_valid_pss_frames); + } + if (cell_detect_config.init_agc) { + srslte_ue_sync_start_agc(&cs.ue_sync, srslte_rf_set_rx_gain_wrapper, cell_detect_config.init_agc); + } + for (freq=0;freq #include #include +#include +#include #include "srslte/config.h" @@ -72,63 +74,56 @@ static void set_default_filter(srslte_chest_dl_t *q, int filter_len) { * * This object depends on the srslte_refsignal_t object for creating the LTE CSR signal. */ - -int srslte_chest_dl_init(srslte_chest_dl_t *q, srslte_cell_t cell) +int srslte_chest_dl_init(srslte_chest_dl_t *q, uint32_t max_prb) { int ret = SRSLTE_ERROR_INVALID_INPUTS; - if (q != NULL && - srslte_cell_isvalid(&cell)) + if (q != NULL) { bzero(q, sizeof(srslte_chest_dl_t)); - ret = srslte_refsignal_cs_init(&q->csr_signal, cell); + ret = srslte_refsignal_cs_init(&q->csr_signal, max_prb); if (ret != SRSLTE_SUCCESS) { fprintf(stderr, "Error initializing CSR signal (%d)\n",ret); goto clean_exit; } - q->tmp_noise = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_REFSIGNAL_MAX_NUM_SF(cell.nof_prb)); + q->tmp_noise = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_REFSIGNAL_MAX_NUM_SF(max_prb)); if (!q->tmp_noise) { perror("malloc"); goto clean_exit; } - q->pilot_estimates = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_REFSIGNAL_MAX_NUM_SF(cell.nof_prb)); + + q->pilot_estimates = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_REFSIGNAL_MAX_NUM_SF(max_prb)); if (!q->pilot_estimates) { perror("malloc"); goto clean_exit; } - q->pilot_estimates_average = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_REFSIGNAL_MAX_NUM_SF(cell.nof_prb)); + q->pilot_estimates_average = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_REFSIGNAL_MAX_NUM_SF(max_prb)); if (!q->pilot_estimates_average) { perror("malloc"); goto clean_exit; } - q->pilot_recv_signal = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_REFSIGNAL_MAX_NUM_SF(cell.nof_prb)); + q->pilot_recv_signal = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_REFSIGNAL_MAX_NUM_SF(max_prb)); if (!q->pilot_recv_signal) { perror("malloc"); goto clean_exit; } - if (srslte_interp_linear_vector_init(&q->srslte_interp_linvec, SRSLTE_NRE*cell.nof_prb)) { + if (srslte_interp_linear_vector_init(&q->srslte_interp_linvec, SRSLTE_NRE*max_prb)) { fprintf(stderr, "Error initializing vector interpolator\n"); goto clean_exit; } - if (srslte_interp_linear_init(&q->srslte_interp_lin, 2*cell.nof_prb, SRSLTE_NRE/2)) { + if (srslte_interp_linear_init(&q->srslte_interp_lin, 2*max_prb, SRSLTE_NRE/2)) { fprintf(stderr, "Error initializing interpolator\n"); goto clean_exit; } - if (srslte_pss_generate(q->pss_signal, cell.id%3)) { - fprintf(stderr, "Error initializing PSS signal for noise estimation\n"); - goto clean_exit; - } - - q->noise_alg = SRSLTE_NOISE_ALG_REFS; + q->noise_alg = SRSLTE_NOISE_ALG_REFS; q->smooth_filter_len = 3; srslte_chest_dl_set_smooth_filter3_coeff(q, 0.1); - q->cell = cell; } ret = SRSLTE_SUCCESS; @@ -162,10 +157,45 @@ void srslte_chest_dl_free(srslte_chest_dl_t *q) bzero(q, sizeof(srslte_chest_dl_t)); } +int srslte_chest_dl_set_cell(srslte_chest_dl_t *q, srslte_cell_t cell) +{ + int ret = SRSLTE_ERROR_INVALID_INPUTS; + if (q != NULL && + srslte_cell_isvalid(&cell)) + { + if (q->cell.id != cell.id || q->cell.nof_prb == 0) { + memcpy(&q->cell, &cell, sizeof(srslte_cell_t)); + ret = srslte_refsignal_cs_set_cell(&q->csr_signal, cell); + if (ret != SRSLTE_SUCCESS) { + fprintf(stderr, "Error initializing CSR signal (%d)\n",ret); + return SRSLTE_ERROR; + } + if (srslte_pss_generate(q->pss_signal, cell.id%3)) { + fprintf(stderr, "Error initializing PSS signal for noise estimation\n"); + return SRSLTE_ERROR; + } + if (srslte_interp_linear_vector_resize(&q->srslte_interp_linvec, SRSLTE_NRE*q->cell.nof_prb)) { + fprintf(stderr, "Error initializing vector interpolator\n"); + return SRSLTE_ERROR; + } + + if (srslte_interp_linear_resize(&q->srslte_interp_lin, 2*q->cell.nof_prb, SRSLTE_NRE/2)) { + fprintf(stderr, "Error initializing interpolator\n"); + return SRSLTE_ERROR; + } + + } + ret = SRSLTE_SUCCESS; + } + + return ret; +} + /* Uses the difference between the averaged and non-averaged pilot estimates */ static float estimate_noise_pilots(srslte_chest_dl_t *q, uint32_t port_id) { int nref=SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id); + /* Substract noisy pilot estimates */ srslte_vec_sub_ccc(q->pilot_estimates_average, q->pilot_estimates, q->tmp_noise, nref); @@ -318,7 +348,8 @@ int srslte_chest_dl_estimate_port(srslte_chest_dl_t *q, cf_t *input, cf_t *ce, u /* Use the known CSR signal to compute Least-squares estimates */ srslte_vec_prod_conj_ccc(q->pilot_recv_signal, q->csr_signal.pilots[port_id/2][sf_idx], - q->pilot_estimates, SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id)); + q->pilot_estimates, SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id)); + if (ce != NULL) { /* Smooth estimates (if applicable) and interpolate */ @@ -370,7 +401,7 @@ int srslte_chest_dl_estimate_multi(srslte_chest_dl_t *q, cf_t *input[SRSLTE_MAX_ int srslte_chest_dl_estimate(srslte_chest_dl_t *q, cf_t *input, cf_t *ce[SRSLTE_MAX_PORTS], uint32_t sf_idx) { uint32_t port_id; - + for (port_id=0;port_idcell.nof_ports;port_id++) { if (srslte_chest_dl_estimate_port(q, input, ce[port_id], sf_idx, port_id, 0)) { return SRSLTE_ERROR; diff --git a/lib/src/phy/ch_estimation/chest_ul.c b/lib/src/phy/ch_estimation/chest_ul.c index 9996fc9c3..f1d4f495a 100644 --- a/lib/src/phy/ch_estimation/chest_ul.c +++ b/lib/src/phy/ch_estimation/chest_ul.c @@ -32,6 +32,8 @@ #include #include #include +#include +#include #include "srslte/config.h" @@ -43,6 +45,8 @@ #define NOF_REFS_SYM (q->cell.nof_prb*SRSLTE_NRE) #define NOF_REFS_SF (NOF_REFS_SYM*2) // 2 reference symbols per subframe +#define MAX_REFS_SF (max_prb*SRSLTE_NRE*2) // 2 reference symbols per subframe + /** 3GPP LTE Downlink channel estimator and equalizer. * Estimates the channel in the resource elements transmitting references and interpolates for the rest * of the resource grid. @@ -52,52 +56,49 @@ * This object depends on the srslte_refsignal_t object for creating the LTE CSR signal. */ -int srslte_chest_ul_init(srslte_chest_ul_t *q, srslte_cell_t cell) +int srslte_chest_ul_init(srslte_chest_ul_t *q, uint32_t max_prb) { int ret = SRSLTE_ERROR_INVALID_INPUTS; - if (q != NULL && - srslte_cell_isvalid(&cell)) + if (q != NULL) { bzero(q, sizeof(srslte_chest_ul_t)); - q->cell = cell; - - ret = srslte_refsignal_ul_init(&q->dmrs_signal, cell); + ret = srslte_refsignal_ul_init(&q->dmrs_signal, max_prb); if (ret != SRSLTE_SUCCESS) { fprintf(stderr, "Error initializing CSR signal (%d)\n",ret); goto clean_exit; } - q->tmp_noise = srslte_vec_malloc(sizeof(cf_t) * NOF_REFS_SF); + q->tmp_noise = srslte_vec_malloc(sizeof(cf_t) * MAX_REFS_SF); if (!q->tmp_noise) { perror("malloc"); goto clean_exit; } - q->pilot_estimates = srslte_vec_malloc(sizeof(cf_t) * NOF_REFS_SF); + q->pilot_estimates = srslte_vec_malloc(sizeof(cf_t) * MAX_REFS_SF); if (!q->pilot_estimates) { perror("malloc"); goto clean_exit; } for (int i=0;i<4;i++) { - q->pilot_estimates_tmp[i] = srslte_vec_malloc(sizeof(cf_t) * NOF_REFS_SF); + q->pilot_estimates_tmp[i] = srslte_vec_malloc(sizeof(cf_t) * MAX_REFS_SF); if (!q->pilot_estimates_tmp[i]) { perror("malloc"); goto clean_exit; } } - q->pilot_recv_signal = srslte_vec_malloc(sizeof(cf_t) * (NOF_REFS_SF+1)); + q->pilot_recv_signal = srslte_vec_malloc(sizeof(cf_t) * (MAX_REFS_SF+1)); if (!q->pilot_recv_signal) { perror("malloc"); goto clean_exit; } - q->pilot_known_signal = srslte_vec_malloc(sizeof(cf_t) * (NOF_REFS_SF+1)); + q->pilot_known_signal = srslte_vec_malloc(sizeof(cf_t) * (MAX_REFS_SF+1)); if (!q->pilot_known_signal) { perror("malloc"); goto clean_exit; } - if (srslte_interp_linear_vector_init(&q->srslte_interp_linvec, NOF_REFS_SYM)) { + if (srslte_interp_linear_vector_init(&q->srslte_interp_linvec, MAX_REFS_SF)) { fprintf(stderr, "Error initializing vector interpolator\n"); goto clean_exit; } @@ -105,12 +106,17 @@ int srslte_chest_ul_init(srslte_chest_ul_t *q, srslte_cell_t cell) q->smooth_filter_len = 3; srslte_chest_ul_set_smooth_filter3_coeff(q, 0.3333); - q->dmrs_signal_configured = false; + q->dmrs_signal_configured = false; + + if (srslte_refsignal_dmrs_pusch_pregen_init(&q->dmrs_signal, &q->dmrs_pregen, max_prb)) { + fprintf(stderr, "Error allocating memory for pregenerated signals\n"); + goto clean_exit; + } } ret = SRSLTE_SUCCESS; - + clean_exit: if (ret != SRSLTE_SUCCESS) { srslte_chest_ul_free(q); @@ -120,9 +126,8 @@ clean_exit: void srslte_chest_ul_free(srslte_chest_ul_t *q) { - if (q->dmrs_signal_configured) { - srslte_refsignal_dmrs_pusch_pregen_free(&q->dmrs_signal, &q->dmrs_pregen); - } + srslte_refsignal_dmrs_pusch_pregen_free(&q->dmrs_signal, &q->dmrs_pregen); + srslte_refsignal_ul_free(&q->dmrs_signal); if (q->tmp_noise) { free(q->tmp_noise); @@ -146,6 +151,30 @@ void srslte_chest_ul_free(srslte_chest_ul_t *q) bzero(q, sizeof(srslte_chest_ul_t)); } +int srslte_chest_ul_set_cell(srslte_chest_ul_t *q, srslte_cell_t cell) +{ + int ret = SRSLTE_ERROR_INVALID_INPUTS; + if (q != NULL && + srslte_cell_isvalid(&cell)) + { + if (cell.id != q->cell.id || q->cell.nof_prb == 0) { + memcpy(&q->cell, &cell, sizeof(srslte_cell_t)); + ret = srslte_refsignal_ul_set_cell(&q->dmrs_signal, cell); + if (ret != SRSLTE_SUCCESS) { + fprintf(stderr, "Error initializing CSR signal (%d)\n",ret); + return SRSLTE_ERROR; + } + + if (srslte_interp_linear_vector_resize(&q->srslte_interp_linvec, NOF_REFS_SF)) { + fprintf(stderr, "Error initializing vector interpolator\n"); + return SRSLTE_ERROR; + } + } + ret = SRSLTE_SUCCESS; + } + return ret; +} + void srslte_chest_ul_set_cfg(srslte_chest_ul_t *q, srslte_refsignal_dmrs_pusch_cfg_t *pusch_cfg, srslte_pucch_cfg_t *pucch_cfg, diff --git a/lib/src/phy/ch_estimation/refsignal_dl.c b/lib/src/phy/ch_estimation/refsignal_dl.c index ec0f0b4e0..fa8a27968 100644 --- a/lib/src/phy/ch_estimation/refsignal_dl.c +++ b/lib/src/phy/ch_estimation/refsignal_dl.c @@ -99,10 +99,39 @@ inline uint32_t srslte_refsignal_cs_nsymbol(uint32_t l, srslte_cp_t cp, uint32_t } -/** Allocates and precomputes the Cell-Specific Reference (CSR) signal for +/** Allocates memory for the 20 slots in a subframe + */ +int srslte_refsignal_cs_init(srslte_refsignal_cs_t * q, uint32_t max_prb) +{ + + int ret = SRSLTE_ERROR_INVALID_INPUTS; + + if (q != NULL) + { + ret = SRSLTE_ERROR; + + for (int p=0;p<2;p++) { + for (int i=0;ipilots[p][i] = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_REFSIGNAL_NUM_SF(max_prb, 2*p)); + if (!q->pilots[p][i]) { + perror("malloc"); + goto free_and_exit; + } + } + } + ret = SRSLTE_SUCCESS; + } +free_and_exit: + if (ret == SRSLTE_ERROR) { + srslte_refsignal_cs_free(q); + } + return ret; +} + +/** Allocates and precomputes the Cell-Specific Reference (CSR) signal for * the 20 slots in a subframe */ -int srslte_refsignal_cs_init(srslte_refsignal_cs_t * q, srslte_cell_t cell) +int srslte_refsignal_cs_set_cell(srslte_refsignal_cs_t * q, srslte_cell_t cell) { uint32_t c_init; @@ -112,76 +141,57 @@ int srslte_refsignal_cs_init(srslte_refsignal_cs_t * q, srslte_cell_t cell) int ret = SRSLTE_ERROR_INVALID_INPUTS; if (q != NULL && - srslte_cell_isvalid(&cell)) + srslte_cell_isvalid(&cell)) { - ret = SRSLTE_ERROR; - - bzero(q, sizeof(srslte_refsignal_cs_t)); - bzero(&seq, sizeof(srslte_sequence_t)); - if (srslte_sequence_init(&seq, 2 * 2 * SRSLTE_MAX_PRB)) { - goto free_and_exit; - } - - if (SRSLTE_CP_ISNORM(cell.cp)) { - N_cp = 1; - } else { - N_cp = 0; - } - - q->cell = cell; - - for (p=0;p<2;p++) { - for (i=0;ipilots[p][i] = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, 2*p)); - if (!q->pilots[p][i]) { - perror("malloc"); - goto free_and_exit; - } - } - } - - for (ns=0;nscell.nof_prb; i++) { - mp = i + SRSLTE_MAX_PRB - cell.nof_prb; - /* save signal */ - q->pilots[p][ns/2][SRSLTE_REFSIGNAL_PILOT_IDX(i,(ns%2)*nsymbols+l,q->cell)] = - (1 - 2 * (float) seq.c[2 * mp]) / sqrt(2) + - _Complex_I * (1 - 2 * (float) seq.c[2 * mp + 1]) / sqrt(2); - } - } - + if (cell.id != q->cell.id || q->cell.nof_prb == 0) { + memcpy(&q->cell, &cell, sizeof(srslte_cell_t)); + + bzero(&seq, sizeof(srslte_sequence_t)); + if (srslte_sequence_init(&seq, 2*2*SRSLTE_MAX_PRB)) { + return SRSLTE_ERROR; } + + if (SRSLTE_CP_ISNORM(cell.cp)) { + N_cp = 1; + } else { + N_cp = 0; + } + + for (ns=0;nscell.nof_prb; i++) { + mp = i + SRSLTE_MAX_PRB - cell.nof_prb; + /* save signal */ + q->pilots[p][ns/2][SRSLTE_REFSIGNAL_PILOT_IDX(i,(ns%2)*nsymbols+l,q->cell)] = + (1 - 2 * (float) seq.c[2 * mp]) / sqrt(2) + + _Complex_I * (1 - 2 * (float) seq.c[2 * mp + 1]) / sqrt(2); + } + } + } + } + srslte_sequence_free(&seq); } - srslte_sequence_free(&seq); ret = SRSLTE_SUCCESS; } -free_and_exit: - if (ret == SRSLTE_ERROR) { - srslte_sequence_free(&seq); - srslte_refsignal_cs_free(q); - } return ret; } /** Deallocates a srslte_refsignal_cs_t object allocated with srslte_refsignal_cs_init */ void srslte_refsignal_cs_free(srslte_refsignal_cs_t * q) { - int i, p; - - for (p=0;p<2;p++) { - for (i=0;ipilots[p][i]) { free(q->pilots[p][i]); } diff --git a/lib/src/phy/ch_estimation/refsignal_ul.c b/lib/src/phy/ch_estimation/refsignal_ul.c index 609ef52d0..a287f8d48 100644 --- a/lib/src/phy/ch_estimation/refsignal_ul.c +++ b/lib/src/phy/ch_estimation/refsignal_ul.c @@ -29,6 +29,7 @@ #include #include #include +#include #include "srslte/phy/common/phy_common.h" #include "srslte/phy/ch_estimation/refsignal_ul.h" @@ -138,8 +139,8 @@ static int generate_n_prs(srslte_refsignal_ul_t * q) { } q->n_prs_pusch[delta_ss][ns] = n_prs; } - srslte_sequence_free(&seq); } + srslte_sequence_free(&seq); return SRSLTE_SUCCESS; } @@ -160,9 +161,9 @@ static int generate_srslte_sequence_hopping_v(srslte_refsignal_ul_t *q) { return SRSLTE_ERROR; } q->v_pusch[ns][delta_ss] = seq.c[ns]; - srslte_sequence_free(&seq); } } + srslte_sequence_free(&seq); return SRSLTE_SUCCESS; } @@ -170,46 +171,24 @@ static int generate_srslte_sequence_hopping_v(srslte_refsignal_ul_t *q) { /** Initializes srslte_refsignal_ul_t object according to 3GPP 36.211 5.5 * */ -int srslte_refsignal_ul_init(srslte_refsignal_ul_t * q, srslte_cell_t cell) +int srslte_refsignal_ul_init(srslte_refsignal_ul_t * q, uint32_t max_prb) { int ret = SRSLTE_ERROR_INVALID_INPUTS; - if (q != NULL && srslte_cell_isvalid(&cell)) { + if (q != NULL) { ret = SRSLTE_ERROR; bzero(q, sizeof(srslte_refsignal_ul_t)); - q->cell = cell; - + // Allocate temporal buffer for computing signal argument - q->tmp_arg = srslte_vec_malloc(SRSLTE_NRE * q->cell.nof_prb * sizeof(cf_t)); + q->tmp_arg = srslte_vec_malloc(SRSLTE_NRE * max_prb * sizeof(cf_t)); if (!q->tmp_arg) { perror("malloc"); goto free_and_exit; } - srslte_pucch_cfg_default(&q->pucch_cfg); - - // Precompute n_prs - if (generate_n_prs(q)) { - goto free_and_exit; - } - - // Precompute group hopping values u. - if (srslte_group_hopping_f_gh(q->f_gh, q->cell.id)) { - goto free_and_exit; - } - - // Precompute sequence hopping values v. Uses f_ss_pusch - if (generate_srslte_sequence_hopping_v(q)) { - goto free_and_exit; - } - - if (srslte_pucch_n_cs_cell(q->cell, q->n_cs_cell)) { - goto free_and_exit; - } - ret = SRSLTE_SUCCESS; } free_and_exit: @@ -226,6 +205,45 @@ void srslte_refsignal_ul_free(srslte_refsignal_ul_t * q) { bzero(q, sizeof(srslte_refsignal_ul_t)); } +/** Initializes srslte_refsignal_ul_t object according to 3GPP 36.211 5.5 + * + */ +int srslte_refsignal_ul_set_cell(srslte_refsignal_ul_t * q, srslte_cell_t cell) +{ + + int ret = SRSLTE_ERROR_INVALID_INPUTS; + + if (q != NULL && srslte_cell_isvalid(&cell)) { + + if (cell.id != q->cell.id || q->cell.nof_prb == 0) { + memcpy(&q->cell, &cell, sizeof(srslte_cell_t)); + + srslte_pucch_cfg_default(&q->pucch_cfg); + + // Precompute n_prs + if (generate_n_prs(q)) { + return SRSLTE_ERROR; + } + + // Precompute group hopping values u. + if (srslte_group_hopping_f_gh(q->f_gh, q->cell.id)) { + return SRSLTE_ERROR; + } + + // Precompute sequence hopping values v. Uses f_ss_pusch + if (generate_srslte_sequence_hopping_v(q)) { + return SRSLTE_ERROR; + } + + if (srslte_pucch_n_cs_cell(q->cell, q->n_cs_cell)) { + return SRSLTE_ERROR; + } + } + ret = SRSLTE_SUCCESS; + } + return ret; +} + void srslte_refsignal_ul_set_cfg(srslte_refsignal_ul_t *q, srslte_refsignal_dmrs_pusch_cfg_t *pusch_cfg, srslte_pucch_cfg_t *pucch_cfg, @@ -363,15 +381,38 @@ void compute_r(srslte_refsignal_ul_t *q, uint32_t nof_prb, uint32_t ns, uint32_t } +int srslte_refsignal_dmrs_pusch_pregen_init(srslte_refsignal_ul_t *q, srslte_refsignal_ul_dmrs_pregen_t *pregen, + uint32_t max_prb) +{ + for (uint32_t sf_idx=0;sf_idxr[cs][sf_idx] = (cf_t**) calloc(sizeof(cf_t*), max_prb + 1); + if (pregen->r[cs][sf_idx]) { + for (uint32_t n=0;n<=max_prb;n++) { + if (srslte_dft_precoding_valid_prb(n)) { + pregen->r[cs][sf_idx][n] = (cf_t*) srslte_vec_malloc(sizeof(cf_t)*n*2*SRSLTE_NRE); + if (pregen->r[cs][sf_idx][n]) { + } else { + return SRSLTE_ERROR; + } + } + } + } else { + return SRSLTE_ERROR; + } + } + } + return SRSLTE_SUCCESS; +} + + int srslte_refsignal_dmrs_pusch_pregen(srslte_refsignal_ul_t *q, srslte_refsignal_ul_dmrs_pregen_t *pregen) { for (uint32_t sf_idx=0;sf_idxr[cs][sf_idx] = (cf_t**) calloc(sizeof(cf_t*), q->cell.nof_prb + 1); if (pregen->r[cs][sf_idx]) { for (uint32_t n=0;n<=q->cell.nof_prb;n++) { if (srslte_dft_precoding_valid_prb(n)) { - pregen->r[cs][sf_idx][n] = (cf_t*) srslte_vec_malloc(sizeof(cf_t)*n*2*SRSLTE_NRE); if (pregen->r[cs][sf_idx][n]) { if (srslte_refsignal_dmrs_pusch_gen(q, n, sf_idx, cs, pregen->r[cs][sf_idx][n])) { return SRSLTE_ERROR; diff --git a/lib/src/phy/ch_estimation/test/chest_test_dl.c b/lib/src/phy/ch_estimation/test/chest_test_dl.c index c60e94d96..f91600872 100644 --- a/lib/src/phy/ch_estimation/test/chest_test_dl.c +++ b/lib/src/phy/ch_estimation/test/chest_test_dl.c @@ -29,6 +29,7 @@ #include #include #include +#include #include "srslte/srslte.h" @@ -128,10 +129,13 @@ int main(int argc, char **argv) { cid = cell.id; max_cid = cell.id; } - + if (srslte_chest_dl_init(&est, cell.nof_prb)) { + fprintf(stderr, "Error initializing equalizer\n"); + goto do_exit; + } while(cid <= max_cid) { cell.id = cid; - if (srslte_chest_dl_init(&est, cell)) { + if (srslte_chest_dl_set_cell(&est, cell)) { fprintf(stderr, "Error initializing equalizer\n"); goto do_exit; } @@ -214,10 +218,10 @@ int main(int argc, char **argv) { } } } - srslte_chest_dl_free(&est); cid+=10; INFO("cid=%d\n", cid); } + srslte_chest_dl_free(&est); ret = 0; diff --git a/lib/src/phy/ch_estimation/test/chest_test_ul.c b/lib/src/phy/ch_estimation/test/chest_test_ul.c index b3b2331da..7b9fbacc9 100644 --- a/lib/src/phy/ch_estimation/test/chest_test_ul.c +++ b/lib/src/phy/ch_estimation/test/chest_test_ul.c @@ -125,13 +125,17 @@ int main(int argc, char **argv) { max_cid = cell.id; } printf("max_cid=%d, cid=%d, cell.id=%d\n", max_cid, cid, cell.id); + if (srslte_chest_ul_init(&est, cell.nof_prb)) { + fprintf(stderr, "Error initializing equalizer\n"); + goto do_exit; + } while(cid <= max_cid) { cell.id = cid; - if (srslte_chest_ul_init(&est, cell)) { + if (srslte_chest_ul_set_cell(&est, cell)) { fprintf(stderr, "Error initializing equalizer\n"); goto do_exit; } - + for (int n=6;n<=cell.nof_prb;n+=5) { if (srslte_dft_precoding_valid_prb(n)) { for (int delta_ss=29;delta_ss #include #include -#include +#include +#include #include "srslte/phy/common/sequence.h" #include "srslte/phy/utils/vector.h" @@ -35,26 +36,71 @@ #define Nc 1600 +#define MAX_SEQ_LEN (128*1024) /* * Pseudo Random Sequence generation. * It follows the 3GPP Release 8 (LTE) 36.211 * Section 7.2 */ -void srslte_sequence_set_LTE_pr(srslte_sequence_t *q, uint32_t seed) { +#ifdef static +static uint8_t x1[Nc+MAX_SEQ_LEN+31]; +static uint8_t x2[Nc+MAX_SEQ_LEN+31]; + +static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; +int srslte_sequence_set_LTE_pr(srslte_sequence_t *q, uint32_t len, uint32_t seed) { + int n; + + if (len > q->max_len) { + fprintf(stderr, "Error generating pseudo-random sequence: len %d exceeds maximum len %d\n", + len, MAX_SEQ_LEN); + return -1; + } + + if (len > q->max_len) { + fprintf(stderr, "Error generating pseudo-random sequence: len %d is greater than allocated len %d\n", + len, q->max_len); + return -1; + } + pthread_mutex_lock(&mutex); + + for (n = 0; n < 31; n++) { + x2[n] = (seed >> n) & 0x1; + } + x1[0] = 1; + + for (n = 0; n < Nc + len; n++) { + x1[n + 31] = (x1[n + 3] + x1[n]) & 0x1; + x2[n + 31] = (x2[n + 3] + x2[n + 2] + x2[n+1] + x2[n]) & 0x1; + } + + for (n = 0; n < len; n++) { + q->c[n] = (x1[n + Nc] + x2[n + Nc]) & 0x1; + } + pthread_mutex_unlock(&mutex); +} + +#else +int srslte_sequence_set_LTE_pr(srslte_sequence_t *q, uint32_t len, uint32_t seed) { int n; uint32_t *x1, *x2; - x1 = calloc(Nc + q->len + 31, sizeof(uint32_t)); + if (len > q->max_len) { + fprintf(stderr, "Error generating pseudo-random sequence: len %d is greater than allocated len %d\n", + len, q->max_len); + return -1; + } + + x1 = calloc(Nc + len + 31, sizeof(uint32_t)); if (!x1) { perror("calloc"); - return; + return -1; } - x2 = calloc(Nc + q->len + 31, sizeof(uint32_t)); + x2 = calloc(Nc + len + 31, sizeof(uint32_t)); if (!x2) { free(x1); perror("calloc"); - return; + return -1; } for (n = 0; n < 31; n++) { @@ -62,45 +108,43 @@ void srslte_sequence_set_LTE_pr(srslte_sequence_t *q, uint32_t seed) { } x1[0] = 1; - for (n = 0; n < Nc + q->len; n++) { + for (n = 0; n < Nc + len; n++) { x1[n + 31] = (x1[n + 3] + x1[n]) & 0x1; x2[n + 31] = (x2[n + 3] + x2[n + 2] + +x2[n+1] + x2[n]) & 0x1; } - for (n = 0; n < q->len; n++) { + for (n = 0; n < len; n++) { q->c[n] = (x1[n + Nc] + x2[n + Nc]) & 0x1; } free(x1); free(x2); + + return 0; } +#endif + int srslte_sequence_LTE_pr(srslte_sequence_t *q, uint32_t len, uint32_t seed) { if (srslte_sequence_init(q, len)) { return SRSLTE_ERROR; } - q->len = len; - srslte_sequence_set_LTE_pr(q, seed); + q->cur_len = len; + srslte_sequence_set_LTE_pr(q, len, seed); srslte_bit_pack_vector(q->c, q->c_bytes, len); for (int i=0;ic_float[i] = (1-2*q->c[i]); q->c_short[i] = (int16_t) q->c_float[i]; } + + + return SRSLTE_SUCCESS; } int srslte_sequence_init(srslte_sequence_t *q, uint32_t len) { - if (q->c && (q->len != len)) { - free(q->c); - if (q->c_bytes) { - free(q->c_bytes); - } - if (q->c_float) { - free(q->c_float); - } - if (q->c_short) { - free(q->c_short); - } + if (q->c && len > q->max_len) { + srslte_sequence_free(q); } if (!q->c) { q->c = srslte_vec_malloc(len * sizeof(uint8_t)); @@ -119,7 +163,7 @@ int srslte_sequence_init(srslte_sequence_t *q, uint32_t len) { if (!q->c_short) { return SRSLTE_ERROR; } - q->len = len; + q->max_len = len; } return SRSLTE_SUCCESS; } diff --git a/lib/src/phy/dft/dft_fftw.c b/lib/src/phy/dft/dft_fftw.c index 347e04547..d841d7d33 100644 --- a/lib/src/phy/dft/dft_fftw.c +++ b/lib/src/phy/dft/dft_fftw.c @@ -29,6 +29,7 @@ #include #include #include +#include #include "srslte/phy/dft/dft.h" #include "srslte/phy/utils/vector.h" @@ -46,11 +47,41 @@ int srslte_dft_plan(srslte_dft_plan_t *plan, const int dft_points, srslte_dft_di return 0; } +int srslte_dft_replan(srslte_dft_plan_t *plan, const int new_dft_points) { + if (new_dft_points <= plan->init_size) { + if(plan->mode == SRSLTE_DFT_COMPLEX){ + return srslte_dft_replan_c(plan,new_dft_points); + } else { + return srslte_dft_replan_r(plan,new_dft_points); + } + } else { + fprintf(stderr, "DFT: Error calling replan: new_dft_points (%d) must be lower or equal " + "dft_size passed initially (%d)\n", new_dft_points, plan->init_size); + return -1; + } +} + + + static void allocate(srslte_dft_plan_t *plan, int size_in, int size_out, int len) { plan->in = fftwf_malloc(size_in*len); plan->out = fftwf_malloc(size_out*len); } +int srslte_dft_replan_c(srslte_dft_plan_t *plan, const int new_dft_points) { + int sign = (plan->dir == SRSLTE_DFT_FORWARD) ? FFTW_FORWARD : FFTW_BACKWARD; + if (plan->p) { + fftwf_destroy_plan(plan->p); + plan->p = NULL; + } + plan->p = fftwf_plan_dft_1d(new_dft_points, plan->in, plan->out, sign, 0U); + if (!plan->p) { + return -1; + } + plan->size = new_dft_points; + return 0; +} + int srslte_dft_plan_c(srslte_dft_plan_t *plan, const int dft_points, srslte_dft_dir_t dir) { allocate(plan,sizeof(fftwf_complex),sizeof(fftwf_complex), dft_points); int sign = (dir == SRSLTE_DFT_FORWARD) ? FFTW_FORWARD : FFTW_BACKWARD; @@ -59,6 +90,7 @@ int srslte_dft_plan_c(srslte_dft_plan_t *plan, const int dft_points, srslte_dft_ return -1; } plan->size = dft_points; + plan->init_size = plan->size; plan->mode = SRSLTE_DFT_COMPLEX; plan->dir = dir; plan->forward = (dir==SRSLTE_DFT_FORWARD)?true:false; @@ -70,6 +102,20 @@ int srslte_dft_plan_c(srslte_dft_plan_t *plan, const int dft_points, srslte_dft_ return 0; } +int srslte_dft_replan_r(srslte_dft_plan_t *plan, const int new_dft_points) { + int sign = (plan->dir == SRSLTE_DFT_FORWARD) ? FFTW_R2HC : FFTW_HC2R; + if (plan->p) { + fftwf_destroy_plan(plan->p); + plan->p = NULL; + } + plan->p = fftwf_plan_r2r_1d(new_dft_points, plan->in, plan->out, sign, 0U); + if (!plan->p) { + return -1; + } + plan->size = new_dft_points; + return 0; +} + int srslte_dft_plan_r(srslte_dft_plan_t *plan, const int dft_points, srslte_dft_dir_t dir) { allocate(plan,sizeof(float),sizeof(float), dft_points); int sign = (dir == SRSLTE_DFT_FORWARD) ? FFTW_R2HC : FFTW_HC2R; @@ -78,6 +124,7 @@ int srslte_dft_plan_r(srslte_dft_plan_t *plan, const int dft_points, srslte_dft_ return -1; } plan->size = dft_points; + plan->init_size = plan->size; plan->mode = SRSLTE_REAL; plan->dir = dir; plan->forward = (dir==SRSLTE_DFT_FORWARD)?true:false; diff --git a/lib/src/phy/dft/dft_precoding.c b/lib/src/phy/dft/dft_precoding.c index 3bec5b96e..a43d79406 100644 --- a/lib/src/phy/dft/dft_precoding.c +++ b/lib/src/phy/dft/dft_precoding.c @@ -40,37 +40,42 @@ #include "srslte/phy/dft/dft_precoding.h" /* Create DFT plans for transform precoding */ -int srslte_dft_precoding_init(srslte_dft_precoding_t *q, uint32_t max_prb) + +int srslte_dft_precoding_init(srslte_dft_precoding_t *q, uint32_t max_prb, bool is_tx) { - int ret = SRSLTE_ERROR_INVALID_INPUTS; + int ret = SRSLTE_ERROR_INVALID_INPUTS; bzero(q, sizeof(srslte_dft_precoding_t)); - + if (max_prb <= SRSLTE_MAX_PRB) { - ret = SRSLTE_ERROR; + ret = SRSLTE_ERROR; for (uint32_t i=1;i<=max_prb;i++) { - if(srslte_dft_precoding_valid_prb(i)) { + if(srslte_dft_precoding_valid_prb(i)) { DEBUG("Initiating DFT precoding plan for %d PRBs\n", i); - if (srslte_dft_plan_c(&q->dft_plan[i], i*SRSLTE_NRE, SRSLTE_DFT_FORWARD)) { + if (srslte_dft_plan_c(&q->dft_plan[i], i*SRSLTE_NRE, is_tx?SRSLTE_DFT_FORWARD:SRSLTE_DFT_BACKWARD)) { fprintf(stderr, "Error: Creating DFT plan %d\n",i); goto clean_exit; } srslte_dft_plan_set_norm(&q->dft_plan[i], true); - if (srslte_dft_plan_c(&q->idft_plan[i], i*SRSLTE_NRE, SRSLTE_DFT_BACKWARD)) { - fprintf(stderr, "Error: Creating DFT plan %d\n",i); - goto clean_exit; - } - srslte_dft_plan_set_norm(&q->idft_plan[i], true); } } q->max_prb = max_prb; ret = SRSLTE_SUCCESS; - } + } -clean_exit: + clean_exit: if (ret == SRSLTE_ERROR) { srslte_dft_precoding_free(q); } - return ret; + return ret; +} + +int srslte_dft_precoding_init_rx(srslte_dft_precoding_t *q, uint32_t max_prb) +{ + return srslte_dft_precoding_init(q, max_prb, false); +} + +int srslte_dft_precoding_init_tx(srslte_dft_precoding_t *q, uint32_t max_prb) { + return srslte_dft_precoding_init(q, max_prb, true); } /* Free DFT plans for transform precoding */ @@ -79,7 +84,6 @@ void srslte_dft_precoding_free(srslte_dft_precoding_t *q) for (uint32_t i=1;i<=q->max_prb;i++) { if(srslte_dft_precoding_valid_prb(i)) { srslte_dft_plan_free(&q->dft_plan[i]); - srslte_dft_plan_free(&q->idft_plan[i]); } } bzero(q, sizeof(srslte_dft_precoding_t)); @@ -98,7 +102,7 @@ bool srslte_dft_precoding_valid_prb(uint32_t nof_prb) { } int srslte_dft_precoding(srslte_dft_precoding_t *q, cf_t *input, cf_t *output, - uint32_t nof_prb, uint32_t nof_symbols) + uint32_t nof_prb, uint32_t nof_symbols) { if (!srslte_dft_precoding_valid_prb(nof_prb) && nof_prb <= q->max_prb) { @@ -112,19 +116,3 @@ int srslte_dft_precoding(srslte_dft_precoding_t *q, cf_t *input, cf_t *output, return SRSLTE_SUCCESS; } - -int srslte_dft_predecoding(srslte_dft_precoding_t *q, cf_t *input, cf_t *output, - uint32_t nof_prb, uint32_t nof_symbols) -{ - if (!srslte_dft_precoding_valid_prb(nof_prb) && nof_prb <= q->max_prb) { - fprintf(stderr, "Error invalid number of PRB (%d)\n", nof_prb); - return SRSLTE_ERROR; - } - - for (uint32_t i=0;iidft_plan[nof_prb], &input[i*SRSLTE_NRE*nof_prb], &output[i*SRSLTE_NRE*nof_prb]); - } - - return SRSLTE_SUCCESS; - -} diff --git a/lib/src/phy/dft/ofdm.c b/lib/src/phy/dft/ofdm.c index 69b7e9161..825aff1e0 100644 --- a/lib/src/phy/dft/ofdm.c +++ b/lib/src/phy/dft/ofdm.c @@ -29,6 +29,7 @@ #include #include #include +#include #include "srslte/phy/common/phy_common.h" #include "srslte/phy/dft/dft.h" @@ -48,6 +49,12 @@ int srslte_ofdm_init_(srslte_ofdm_t *q, srslte_cp_t cp, int symbol_sz, int nof_p return -1; } + q->shift_buffer = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN(symbol_sz)); + if (!q->shift_buffer) { + perror("malloc"); + return -1; + } + srslte_dft_plan_set_mirror(&q->fft_plan, true); srslte_dft_plan_set_dc(&q->fft_plan, true); @@ -55,7 +62,6 @@ int srslte_ofdm_init_(srslte_ofdm_t *q, srslte_cp_t cp, int symbol_sz, int nof_p q->nof_symbols = SRSLTE_CP_NSYMB(cp); q->cp = cp; q->freq_shift = false; - q->shift_buffer = NULL; q->nof_re = nof_prb * SRSLTE_NRE; q->nof_guards = ((symbol_sz - q->nof_re) / 2); q->slot_sz = SRSLTE_SLOT_LEN(symbol_sz); @@ -67,6 +73,32 @@ int srslte_ofdm_init_(srslte_ofdm_t *q, srslte_cp_t cp, int symbol_sz, int nof_p return SRSLTE_SUCCESS; } + +int srslte_ofdm_replan_(srslte_ofdm_t *q, srslte_cp_t cp, int symbol_sz, int nof_prb) { + + if (srslte_dft_replan_c(&q->fft_plan, symbol_sz)) { + fprintf(stderr, "Error: Creating DFT plan\n"); + return -1; + } + + q->symbol_sz = (uint32_t) symbol_sz; + q->nof_symbols = SRSLTE_CP_NSYMB(cp); + q->cp = cp; + q->nof_re = nof_prb * SRSLTE_NRE; + q->nof_guards = ((symbol_sz - q->nof_re) / 2); + q->slot_sz = SRSLTE_SLOT_LEN(symbol_sz); + + if (q->freq_shift) { + srslte_ofdm_set_freq_shift(q, q->freq_shift_f); + } + + DEBUG("Replan symbol_sz=%d, nof_symbols=%d, cp=%s, nof_re=%d, nof_guards=%d\n", + q->symbol_sz, q->nof_symbols, + q->cp==SRSLTE_CP_NORM?"Normal":"Extended", q->nof_re, q->nof_guards); + + return SRSLTE_SUCCESS; +} + void srslte_ofdm_free_(srslte_ofdm_t *q) { srslte_dft_plan_free(&q->fft_plan); if (q->tmp) { @@ -78,30 +110,28 @@ void srslte_ofdm_free_(srslte_ofdm_t *q) { bzero(q, sizeof(srslte_ofdm_t)); } -int srslte_ofdm_rx_init(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t nof_prb) { - int symbol_sz = srslte_symbol_sz(nof_prb); +int srslte_ofdm_rx_init(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t max_prb) { + int symbol_sz = srslte_symbol_sz(max_prb); if (symbol_sz < 0) { - fprintf(stderr, "Error: Invalid nof_prb=%d\n", nof_prb); + fprintf(stderr, "Error: Invalid nof_prb=%d\n", max_prb); return -1; } - return srslte_ofdm_init_(q, cp, symbol_sz, nof_prb, SRSLTE_DFT_FORWARD); + q->max_prb = max_prb; + return srslte_ofdm_init_(q, cp, symbol_sz, max_prb, SRSLTE_DFT_FORWARD); } -void srslte_ofdm_rx_free(srslte_ofdm_t *q) { - srslte_ofdm_free_(q); -} - -int srslte_ofdm_tx_init(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t nof_prb) { +int srslte_ofdm_tx_init(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t max_prb) { uint32_t i; int ret; - int symbol_sz = srslte_symbol_sz(nof_prb); + int symbol_sz = srslte_symbol_sz(max_prb); if (symbol_sz < 0) { - fprintf(stderr, "Error: Invalid nof_prb=%d\n", nof_prb); + fprintf(stderr, "Error: Invalid nof_prb=%d\n", max_prb); return -1; } + q->max_prb = max_prb; - ret = srslte_ofdm_init_(q, cp, symbol_sz, nof_prb, SRSLTE_DFT_BACKWARD); + ret = srslte_ofdm_init_(q, cp, symbol_sz, max_prb, SRSLTE_DFT_BACKWARD); if (ret == SRSLTE_SUCCESS) { srslte_dft_plan_set_norm(&q->fft_plan, false); @@ -115,16 +145,57 @@ int srslte_ofdm_tx_init(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t nof_prb) { return ret; } +int srslte_ofdm_rx_set_prb(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t nof_prb) { + if (nof_prb <= q->max_prb) { + int symbol_sz = srslte_symbol_sz(nof_prb); + if (symbol_sz < 0) { + fprintf(stderr, "Error: Invalid nof_prb=%d\n", nof_prb); + return -1; + } + return srslte_ofdm_replan_(q, cp, symbol_sz, nof_prb); + } else { + fprintf(stderr, "OFDM: Error calling set_prb: nof_prb must be equal or lower initialized max_prb\n"); + return -1; + } +} + +int srslte_ofdm_tx_set_prb(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t nof_prb) { + uint32_t i; + int ret; + + if (nof_prb <= q->max_prb) { + int symbol_sz = srslte_symbol_sz(nof_prb); + if (symbol_sz < 0) { + fprintf(stderr, "Error: Invalid nof_prb=%d\n", nof_prb); + return -1; + } + + ret = srslte_ofdm_replan_(q, cp, symbol_sz, nof_prb); + + if (ret == SRSLTE_SUCCESS) { + /* set now zeros at CP */ + for (i=0;inof_symbols;i++) { + bzero(q->tmp, q->nof_guards * sizeof(cf_t)); + bzero(&q->tmp[q->nof_re + q->nof_guards], q->nof_guards * sizeof(cf_t)); + } + } + return ret; + } else { + fprintf(stderr, "OFDM: Error calling set_prb: nof_prb must be equal or lower initialized max_prb\n"); + return -1; + } +} + + +void srslte_ofdm_rx_free(srslte_ofdm_t *q) { + srslte_ofdm_free_(q); +} + /* Shifts the signal after the iFFT or before the FFT. * Freq_shift is relative to inter-carrier spacing. * Caution: This function shall not be called during run-time */ int srslte_ofdm_set_freq_shift(srslte_ofdm_t *q, float freq_shift) { - q->shift_buffer = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN(q->symbol_sz)); - if (!q->shift_buffer) { - perror("malloc"); - return -1; - } cf_t *ptr = q->shift_buffer; for (uint32_t n=0;n<2;n++) { for (uint32_t i=0;inof_symbols;i++) { @@ -140,7 +211,7 @@ int srslte_ofdm_set_freq_shift(srslte_ofdm_t *q, float freq_shift) { srslte_dft_plan_set_dc(&q->fft_plan, false); q->freq_shift = true; - + q->freq_shift_f = freq_shift; return SRSLTE_SUCCESS; } diff --git a/lib/src/phy/enb/enb_dl.c b/lib/src/phy/enb/enb_dl.c index 4cc33d3b8..095312621 100644 --- a/lib/src/phy/enb/enb_dl.c +++ b/lib/src/phy/enb/enb_dl.c @@ -29,6 +29,7 @@ #include #include #include +#include #define CURRENT_FFTSIZE srslte_symbol_sz(q->cell.nof_prb) @@ -39,61 +40,55 @@ #define SRSLTE_ENB_RF_AMP 0.1 -int srslte_enb_dl_init(srslte_enb_dl_t *q, srslte_cell_t cell) +int srslte_enb_dl_init(srslte_enb_dl_t *q, uint32_t max_prb) { int ret = SRSLTE_ERROR_INVALID_INPUTS; - if (q != NULL && - srslte_cell_isvalid(&cell)) + if (q != NULL) { ret = SRSLTE_ERROR; bzero(q, sizeof(srslte_enb_dl_t)); - q->cell = cell; - q->cfi = 3; + q->cfi = 3; q->tx_amp = SRSLTE_ENB_RF_AMP; - if (srslte_ofdm_tx_init(&q->ifft, q->cell.cp, q->cell.nof_prb)) { + if (srslte_ofdm_tx_init(&q->ifft, SRSLTE_CP_NORM, max_prb)) { fprintf(stderr, "Error initiating FFT\n"); goto clean_exit; } srslte_ofdm_set_normalize(&q->ifft, true); - if (srslte_regs_init(&q->regs, q->cell)) { - fprintf(stderr, "Error initiating REGs\n"); - goto clean_exit; - } - if (srslte_pbch_init(&q->pbch, q->cell)) { + if (srslte_pbch_init(&q->pbch)) { fprintf(stderr, "Error creating PBCH object\n"); goto clean_exit; } - if (srslte_pcfich_init(&q->pcfich, &q->regs, q->cell)) { + if (srslte_pcfich_init(&q->pcfich)) { fprintf(stderr, "Error creating PCFICH object\n"); goto clean_exit; } - if (srslte_phich_init(&q->phich, &q->regs, q->cell)) { + if (srslte_phich_init(&q->phich)) { fprintf(stderr, "Error creating PHICH object\n"); goto clean_exit; } - if (srslte_pdcch_init(&q->pdcch, &q->regs, q->cell)) { + if (srslte_pdcch_init(&q->pdcch, max_prb)) { fprintf(stderr, "Error creating PDCCH object\n"); goto clean_exit; } - if (srslte_pdsch_init(&q->pdsch, q->cell)) { + if (srslte_pdsch_init_enb(&q->pdsch, max_prb)) { fprintf(stderr, "Error creating PDSCH object\n"); goto clean_exit; } - if (srslte_refsignal_cs_init(&q->csr_signal, q->cell)) { + if (srslte_refsignal_cs_init(&q->csr_signal, max_prb)) { fprintf(stderr, "Error initializing CSR signal (%d)\n",ret); goto clean_exit; } - for (int i=0;icell.nof_ports;i++) { + for (int i=0;isf_symbols[i] = srslte_vec_malloc(CURRENT_SFLEN_RE * sizeof(cf_t)); if (!q->sf_symbols[i]) { perror("malloc"); @@ -102,15 +97,10 @@ int srslte_enb_dl_init(srslte_enb_dl_t *q, srslte_cell_t cell) q->slot1_symbols[i] = &q->sf_symbols[i][CURRENT_SLOTLEN_RE]; } - /* Generate PSS/SSS signals */ - srslte_pss_generate(q->pss_signal, cell.id%3); - srslte_sss_generate(q->sss_signal0, q->sss_signal5, cell.id); - ret = SRSLTE_SUCCESS; } else { - fprintf(stderr, "Invalid cell properties: Id=%d, Ports=%d, PRBs=%d\n", - cell.id, cell.nof_ports, cell.nof_prb); + fprintf(stderr, "Invalid parameters\n"); } clean_exit: @@ -141,6 +131,71 @@ void srslte_enb_dl_free(srslte_enb_dl_t *q) } } +int srslte_enb_dl_set_cell(srslte_enb_dl_t *q, srslte_cell_t cell) +{ + int ret = SRSLTE_ERROR_INVALID_INPUTS; + + if (q != NULL && + srslte_cell_isvalid(&cell)) + { + q->cfi = 3; + q->tx_amp = SRSLTE_ENB_RF_AMP; + + if (q->cell.id != cell.id || q->cell.nof_prb == 0) { + if (q->cell.nof_prb) { + if (srslte_regs_init(&q->regs, q->cell)) { + fprintf(stderr, "Error initiating REGs\n"); + return SRSLTE_ERROR; + } + } + memcpy(&q->cell, &cell, sizeof(srslte_cell_t)); + + if (srslte_ofdm_rx_set_prb(&q->ifft, q->cell.cp, q->cell.nof_prb)) { + fprintf(stderr, "Error initiating FFT\n"); + return SRSLTE_ERROR; + } + if (srslte_pbch_set_cell(&q->pbch, q->cell)) { + fprintf(stderr, "Error creating PBCH object\n"); + return SRSLTE_ERROR; + } + if (srslte_pcfich_set_cell(&q->pcfich, &q->regs, q->cell)) { + fprintf(stderr, "Error creating PCFICH object\n"); + return SRSLTE_ERROR; + } + if (srslte_phich_set_cell(&q->phich, &q->regs, q->cell)) { + fprintf(stderr, "Error creating PHICH object\n"); + return SRSLTE_ERROR; + } + + if (srslte_pdcch_set_cell(&q->pdcch, &q->regs, q->cell)) { + fprintf(stderr, "Error creating PDCCH object\n"); + return SRSLTE_ERROR; + } + + if (srslte_pdsch_set_cell(&q->pdsch, q->cell)) { + fprintf(stderr, "Error creating PDSCH object\n"); + return SRSLTE_ERROR; + } + + if (srslte_refsignal_cs_set_cell(&q->csr_signal, q->cell)) { + fprintf(stderr, "Error initializing CSR signal (%d)\n",ret); + return SRSLTE_ERROR; + } + /* Generate PSS/SSS signals */ + srslte_pss_generate(q->pss_signal, cell.id%3); + srslte_sss_generate(q->sss_signal0, q->sss_signal5, cell.id); + } + ret = SRSLTE_SUCCESS; + + } else { + fprintf(stderr, "Invalid cell properties: Id=%d, Ports=%d, PRBs=%d\n", + cell.id, cell.nof_ports, cell.nof_prb); + } + return ret; +} + + + void srslte_enb_dl_set_amp(srslte_enb_dl_t *q, float amp) { q->tx_amp = amp; diff --git a/lib/src/phy/enb/enb_ul.c b/lib/src/phy/enb/enb_ul.c index 9c294ac43..653091935 100644 --- a/lib/src/phy/enb/enb_ul.c +++ b/lib/src/phy/enb/enb_ul.c @@ -39,78 +39,54 @@ #define MAX_CANDIDATES 16 -int srslte_enb_ul_init(srslte_enb_ul_t *q, srslte_cell_t cell, - srslte_prach_cfg_t *prach_cfg, - srslte_refsignal_dmrs_pusch_cfg_t *pusch_cfg, - srslte_pusch_hopping_cfg_t *hopping_cfg, - srslte_pucch_cfg_t *pucch_cfg) +int srslte_enb_ul_init(srslte_enb_ul_t *q, + uint32_t max_prb) { int ret = SRSLTE_ERROR_INVALID_INPUTS; - if (q != NULL && - srslte_cell_isvalid(&cell)) + if (q != NULL) { ret = SRSLTE_ERROR; bzero(q, sizeof(srslte_enb_ul_t)); - q->cell = cell; - - if (hopping_cfg) { - memcpy(&q->hopping_cfg, hopping_cfg, sizeof(srslte_pusch_hopping_cfg_t)); - } - q->users = calloc(sizeof(srslte_enb_ul_user_t*), SRSLTE_SIRNTI); if (!q->users) { perror("malloc"); goto clean_exit; } - if (srslte_ofdm_rx_init(&q->fft, q->cell.cp, q->cell.nof_prb)) { + if (srslte_ofdm_rx_init(&q->fft, SRSLTE_CP_NORM, max_prb)) { fprintf(stderr, "Error initiating FFT\n"); goto clean_exit; } srslte_ofdm_set_normalize(&q->fft, false); srslte_ofdm_set_freq_shift(&q->fft, -0.5); - if (srslte_pucch_init(&q->pucch, q->cell)) { + if (srslte_pucch_init(&q->pucch)) { fprintf(stderr, "Error creating PUCCH object\n"); goto clean_exit; } - if (srslte_pusch_init(&q->pusch, q->cell)) { + if (srslte_pusch_init_enb(&q->pusch, max_prb)) { fprintf(stderr, "Error creating PUSCH object\n"); goto clean_exit; } - - if (prach_cfg) { - if (srslte_prach_init_cfg(&q->prach, prach_cfg, q->cell.nof_prb)) { - fprintf(stderr, "Error initiating PRACH\n"); - goto clean_exit; - } - srslte_prach_set_detect_factor(&q->prach, 60); - } - + srslte_pucch_set_threshold(&q->pucch, 0.5, 0.5); - if (srslte_chest_ul_init(&q->chest, cell)) { + if (srslte_chest_ul_init(&q->chest, max_prb)) { fprintf(stderr, "Error initiating channel estimator\n"); goto clean_exit; } - - // Configure common PUCCH configuration - srslte_pucch_set_cfg(&q->pucch, pucch_cfg, pusch_cfg->group_hopping_en); - - // SRS is a dedicated configuration - srslte_chest_ul_set_cfg(&q->chest, pusch_cfg, pucch_cfg, NULL); - - q->sf_symbols = srslte_vec_malloc(CURRENT_SFLEN_RE * sizeof(cf_t)); + + q->sf_symbols = srslte_vec_malloc(SRSLTE_SF_LEN_RE(max_prb, SRSLTE_CP_NORM) * sizeof(cf_t)); if (!q->sf_symbols) { perror("malloc"); goto clean_exit; } - q->ce = srslte_vec_malloc(CURRENT_SFLEN_RE * sizeof(cf_t)); + q->ce = srslte_vec_malloc(SRSLTE_SF_LEN_RE(max_prb, SRSLTE_CP_NORM) * sizeof(cf_t)); if (!q->ce) { perror("malloc"); goto clean_exit; @@ -119,8 +95,7 @@ int srslte_enb_ul_init(srslte_enb_ul_t *q, srslte_cell_t cell, ret = SRSLTE_SUCCESS; } else { - fprintf(stderr, "Invalid cell properties: Id=%d, Ports=%d, PRBs=%d\n", - cell.id, cell.nof_ports, cell.nof_prb); + fprintf(stderr, "Invalid parameters\n"); } clean_exit: @@ -158,6 +133,70 @@ void srslte_enb_ul_free(srslte_enb_ul_t *q) } } +int srslte_enb_ul_set_cell(srslte_enb_ul_t *q, srslte_cell_t cell, + srslte_prach_cfg_t *prach_cfg, + srslte_refsignal_dmrs_pusch_cfg_t *pusch_cfg, + srslte_pusch_hopping_cfg_t *hopping_cfg, + srslte_pucch_cfg_t *pucch_cfg) +{ + int ret = SRSLTE_ERROR_INVALID_INPUTS; + + if (q != NULL && + srslte_cell_isvalid(&cell)) + { + if (cell.id != q->cell.id || q->cell.nof_prb == 0) { + memcpy(&q->cell, &cell, sizeof(srslte_cell_t)); + + if (hopping_cfg) { + memcpy(&q->hopping_cfg, hopping_cfg, sizeof(srslte_pusch_hopping_cfg_t)); + } + + if (srslte_ofdm_rx_set_prb(&q->fft, q->cell.cp, q->cell.nof_prb)) { + fprintf(stderr, "Error initiating FFT\n"); + return SRSLTE_ERROR; + } + + if (srslte_pucch_set_cell(&q->pucch, q->cell)) { + fprintf(stderr, "Error creating PUCCH object\n"); + return SRSLTE_ERROR; + } + + if (srslte_pusch_set_cell(&q->pusch, q->cell)) { + fprintf(stderr, "Error creating PUSCH object\n"); + return SRSLTE_ERROR; + } + + if (prach_cfg) { + if (srslte_prach_init_cfg(&q->prach, prach_cfg, q->cell.nof_prb)) { + fprintf(stderr, "Error initiating PRACH\n"); + return SRSLTE_ERROR; + } + srslte_prach_set_detect_factor(&q->prach, 60); + } + + srslte_pucch_set_threshold(&q->pucch, 0.5, 0.5); + + if (srslte_chest_ul_set_cell(&q->chest, cell)) { + fprintf(stderr, "Error initiating channel estimator\n"); + return SRSLTE_ERROR; + } + + // Configure common PUCCH configuration + srslte_pucch_set_cfg(&q->pucch, pucch_cfg, pusch_cfg->group_hopping_en); + + // SRS is a dedicated configuration + srslte_chest_ul_set_cfg(&q->chest, pusch_cfg, pucch_cfg, NULL); + + ret = SRSLTE_SUCCESS; + } + } else { + fprintf(stderr, "Invalid cell properties: Id=%d, Ports=%d, PRBs=%d\n", + cell.id, cell.nof_ports, cell.nof_prb); + } + return ret; +} + + int srslte_enb_ul_add_rnti(srslte_enb_ul_t *q, uint16_t rnti) { if (!q->users[rnti]) { diff --git a/lib/src/phy/phch/pbch.c b/lib/src/phy/phch/pbch.c index 783ae1e04..dfd094dec 100644 --- a/lib/src/phy/phch/pbch.c +++ b/lib/src/phy/phch/pbch.c @@ -32,6 +32,8 @@ #include #include #include +#include +#include #include "prb_dl.h" #include "srslte/phy/phch/pbch.h" @@ -43,7 +45,6 @@ #define PBCH_RE_CP_NORM 240 #define PBCH_RE_CP_EXT 216 - const uint8_t srslte_crc_mask[4][16] = { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, @@ -139,33 +140,18 @@ int srslte_pbch_get(cf_t *slot1_data, cf_t *pbch, srslte_cell_t cell) { * At the receiver, the field nof_ports in the cell structure indicates the * maximum number of BS transmitter ports to look for. */ -int srslte_pbch_init(srslte_pbch_t *q, srslte_cell_t cell) { +int srslte_pbch_init(srslte_pbch_t *q) { int ret = SRSLTE_ERROR_INVALID_INPUTS; - if (q != NULL && - srslte_cell_isvalid(&cell)) + if (q != NULL) { ret = SRSLTE_ERROR; bzero(q, sizeof(srslte_pbch_t)); - - if (cell.nof_ports == 0) { - q->search_all_ports = true; - cell.nof_ports = SRSLTE_MAX_PORTS; - } else { - q->search_all_ports = false; - } - - q->cell = cell; - q->nof_symbols = (SRSLTE_CP_ISNORM(q->cell.cp)) ? PBCH_RE_CP_NORM : PBCH_RE_CP_EXT; - + if (srslte_modem_table_lte(&q->mod, SRSLTE_MOD_QPSK)) { goto clean; } - if (srslte_sequence_pbch(&q->seq, q->cell.cp, q->cell.id)) { - goto clean; - } - int poly[3] = { 0x6D, 0x4F, 0x57 }; if (srslte_viterbi_init(&q->decoder, SRSLTE_VITERBI_37, poly, 40, true)) { goto clean; @@ -178,12 +164,14 @@ int srslte_pbch_init(srslte_pbch_t *q, srslte_cell_t cell) { q->encoder.tail_biting = true; memcpy(q->encoder.poly, poly, 3 * sizeof(int)); + q->nof_symbols = PBCH_RE_CP_NORM; + q->d = srslte_vec_malloc(sizeof(cf_t) * q->nof_symbols); if (!q->d) { goto clean; } int i; - for (i = 0; i < q->cell.nof_ports; i++) { + for (i = 0; i < SRSLTE_MAX_PORTS; i++) { q->ce[i] = srslte_vec_malloc(sizeof(cf_t) * q->nof_symbols); if (!q->ce[i]) { goto clean; @@ -209,6 +197,7 @@ int srslte_pbch_init(srslte_pbch_t *q, srslte_cell_t cell) { if (!q->rm_b) { goto clean; } + ret = SRSLTE_SUCCESS; } clean: @@ -219,11 +208,11 @@ clean: } void srslte_pbch_free(srslte_pbch_t *q) { - if (q->d) { - free(q->d); - } + srslte_sequence_free(&q->seq); + srslte_modem_table_free(&q->mod); + srslte_viterbi_free(&q->decoder); int i; - for (i = 0; i < q->cell.nof_ports; i++) { + for (i = 0; i < SRSLTE_MAX_PORTS; i++) { if (q->ce[i]) { free(q->ce[i]); } @@ -243,12 +232,37 @@ void srslte_pbch_free(srslte_pbch_t *q) { if (q->rm_b) { free(q->rm_b); } - srslte_sequence_free(&q->seq); - srslte_modem_table_free(&q->mod); - srslte_viterbi_free(&q->decoder); - + if (q->d) { + free(q->d); + } bzero(q, sizeof(srslte_pbch_t)); +} +int srslte_pbch_set_cell(srslte_pbch_t *q, srslte_cell_t cell) { + int ret = SRSLTE_ERROR_INVALID_INPUTS; + + if (q != NULL && + srslte_cell_isvalid(&cell)) + { + if (cell.nof_ports == 0) { + q->search_all_ports = true; + cell.nof_ports = SRSLTE_MAX_PORTS; + } else { + q->search_all_ports = false; + } + + if (q->cell.id != cell.id || q->cell.nof_prb == 0) { + memcpy(&q->cell, &cell, sizeof(srslte_cell_t)); + + if (srslte_sequence_pbch(&q->seq, q->cell.cp, q->cell.id)) { + return SRSLTE_ERROR; + } + } + q->nof_symbols = (SRSLTE_CP_ISNORM(q->cell.cp)) ? PBCH_RE_CP_NORM : PBCH_RE_CP_EXT; + + ret = SRSLTE_SUCCESS; + } + return ret; } @@ -476,6 +490,7 @@ int srslte_pbch_decode(srslte_pbch_t *q, cf_t *slot1_symbols, cf_t *ce_slot1[SRS } else { nant = q->cell.nof_ports; } + do { if (nant != 3) { DEBUG("Trying %d TX antennas with %d frames\n", nant, q->frame_idx); @@ -486,7 +501,7 @@ int srslte_pbch_decode(srslte_pbch_t *q, cf_t *slot1_symbols, cf_t *ce_slot1[SRS srslte_predecoding_single(q->symbols[0], q->ce[0], q->d, q->nof_symbols, noise_estimate); } else { srslte_predecoding_diversity(q->symbols[0], q->ce, x, nant, - q->nof_symbols); + q->nof_symbols); srslte_layerdemap_diversity(x, q->d, nant, q->nof_symbols / nant); } @@ -577,7 +592,7 @@ int srslte_pbch_encode(srslte_pbch_t *q, uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_ if (q->cell.nof_ports > 1) { srslte_layermap_diversity(q->d, x, q->cell.nof_ports, q->nof_symbols); srslte_precoding_diversity(x, q->symbols, q->cell.nof_ports, - q->nof_symbols / q->cell.nof_ports); + q->nof_symbols / q->cell.nof_ports); } else { memcpy(q->symbols[0], q->d, q->nof_symbols * sizeof(cf_t)); } diff --git a/lib/src/phy/phch/pcfich.c b/lib/src/phy/phch/pcfich.c index ec1e13abc..b38c0266f 100644 --- a/lib/src/phy/phch/pcfich.c +++ b/lib/src/phy/phch/pcfich.c @@ -57,38 +57,28 @@ bool srslte_pcfich_exists(int nframe, int nslot) { return true; } -int srslte_pcfich_init(srslte_pcfich_t *q, srslte_regs_t *regs, srslte_cell_t cell) { - return srslte_pcfich_init_multi(q, regs, cell, 1); +int srslte_pcfich_init(srslte_pcfich_t *q) { + return srslte_pcfich_init_multi(q, 1); } /** Initializes the pcfich channel receiver. * On error, returns -1 and frees the structrure */ -int srslte_pcfich_init_multi(srslte_pcfich_t *q, srslte_regs_t *regs, srslte_cell_t cell, uint32_t nof_rx_antennas) { +int srslte_pcfich_init_multi(srslte_pcfich_t *q, uint32_t nof_rx_antennas) { int ret = SRSLTE_ERROR_INVALID_INPUTS; - if (q != NULL && - regs != NULL && - srslte_cell_isvalid(&cell)) + if (q != NULL) { ret = SRSLTE_ERROR; bzero(q, sizeof(srslte_pcfich_t)); - q->cell = cell; - q->regs = regs; + q->nof_rx_antennas = nof_rx_antennas; q->nof_symbols = PCFICH_RE; - q->nof_rx_antennas = nof_rx_antennas; - + if (srslte_modem_table_lte(&q->mod, SRSLTE_MOD_QPSK)) { goto clean; } - for (int nsf = 0; nsf < SRSLTE_NSUBFRAMES_X_FRAME; nsf++) { - if (srslte_sequence_pcfich(&q->seq[nsf], 2 * nsf, q->cell.id)) { - goto clean; - } - } - /* convert cfi bit tables to floats for demodulation */ for (int i=0;i<3;i++) { for (int j=0;jregs = regs; + if (cell.id != q->cell.id || q->cell.nof_prb == 0) { + memcpy(&q->cell, &cell, sizeof(srslte_cell_t)); + for (int nsf = 0; nsf < SRSLTE_NSUBFRAMES_X_FRAME; nsf++) { + if (srslte_sequence_pcfich(&q->seq[nsf], 2 * nsf, q->cell.id)) { + return SRSLTE_ERROR; + } + } + } + ret = SRSLTE_SUCCESS; + } + return ret; +} + + /** Finds the CFI with minimum distance with the vector of received 32 bits. * Saves the CFI value in the cfi pointer and returns the distance. */ @@ -197,7 +209,7 @@ int srslte_pcfich_decode_multi(srslte_pcfich_t *q, cf_t *sf_symbols[SRSLTE_MAX_P } q_symbols[j] = q->symbols[j]; - + /* extract channel estimates */ for (i = 0; i < q->cell.nof_ports; i++) { if (q->nof_symbols != srslte_regs_pcfich_get(q->regs, ce[i][j], q->ce[i][j])) { diff --git a/lib/src/phy/phch/pdcch.c b/lib/src/phy/phch/pdcch.c index cfdb19621..60ab136af 100644 --- a/lib/src/phy/phch/pdcch.c +++ b/lib/src/phy/phch/pdcch.c @@ -61,29 +61,24 @@ float srslte_pdcch_coderate(uint32_t nof_bits, uint32_t l) { } /** Initializes the PDCCH transmitter and receiver */ -int srslte_pdcch_init(srslte_pdcch_t *q, srslte_regs_t *regs, srslte_cell_t cell) { - return srslte_pdcch_init_multi(q, regs, cell, 1); +int srslte_pdcch_init(srslte_pdcch_t *q, uint32_t max_prb) { + return srslte_pdcch_init_multi(q, max_prb, 1); } -int srslte_pdcch_init_multi(srslte_pdcch_t *q, srslte_regs_t *regs, srslte_cell_t cell, uint32_t nof_rx_antennas) +int srslte_pdcch_init_multi(srslte_pdcch_t *q, uint32_t max_prb, uint32_t nof_rx_antennas) { int ret = SRSLTE_ERROR_INVALID_INPUTS; - if (q != NULL && - regs != NULL && - srslte_cell_isvalid(&cell)) + if (q != NULL) { ret = SRSLTE_ERROR; bzero(q, sizeof(srslte_pdcch_t)); - q->cell = cell; - q->regs = regs; - q->nof_rx_antennas = nof_rx_antennas; + q->nof_rx_antennas = nof_rx_antennas; /* Allocate memory for the maximum number of PDCCH bits (CFI=3) */ - q->max_bits = (srslte_regs_pdcch_nregs(q->regs, 3) / 9) * 72; + q->max_bits = max_prb*3*12*2; - INFO("Init PDCCH: Max bits: %d, %d ports.\n", - q->max_bits, q->cell.nof_ports); + INFO("Init PDCCH: Max bits: %d\n", q->max_bits); if (srslte_modem_table_lte(&q->mod, SRSLTE_MOD_QPSK)) { goto clean; @@ -92,14 +87,6 @@ int srslte_pdcch_init_multi(srslte_pdcch_t *q, srslte_regs_t *regs, srslte_cell_ goto clean; } - for (int i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) { - // 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 (srslte_sequence_pdcch(&q->seq[i], 2 * i, q->cell.id, 8*srslte_regs_pdcch_nregs(q->regs, 3))) { - goto clean; - } - } - int poly[3] = { 0x6D, 0x4F, 0x57 }; if (srslte_viterbi_init(&q->decoder, SRSLTE_VITERBI_37, poly, SRSLTE_DCI_MAX_BITS + 16, true)) { goto clean; @@ -187,6 +174,39 @@ void srslte_pdcch_free(srslte_pdcch_t *q) { } +int srslte_pdcch_set_cell(srslte_pdcch_t *q, srslte_regs_t *regs, srslte_cell_t cell) +{ + int ret = SRSLTE_ERROR_INVALID_INPUTS; + + if (q != NULL && + regs != NULL && + srslte_cell_isvalid(&cell)) + { + q->regs = regs; + + /* Allocate memory for the maximum number of PDCCH bits (CFI=3) */ + q->max_bits = (srslte_regs_pdcch_nregs(q->regs, 3) / 9) * 72; + + INFO("PDCCH: Cell config PCI=%d, %d ports.\n", + q->cell.id, q->cell.nof_ports); + + if (q->cell.id != cell.id || q->cell.nof_prb == 0) { + memcpy(&q->cell, &cell, sizeof(srslte_cell_t)); + + for (int i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) { + // 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 (srslte_sequence_pdcch(&q->seq[i], 2 * i, q->cell.id, 8*srslte_regs_pdcch_nregs(q->regs, 3))) { + return SRSLTE_ERROR; + } + } + } + ret = SRSLTE_SUCCESS; + } + return ret; +} + + uint32_t srslte_pdcch_ue_locations(srslte_pdcch_t *q, srslte_dci_location_t *c, uint32_t max_candidates, uint32_t nsubframe, uint32_t cfi, uint16_t rnti) { @@ -472,7 +492,7 @@ int srslte_pdcch_extract_llr_multi(srslte_pdcch_t *q, cf_t *sf_symbols[SRSLTE_MA /* descramble */ srslte_scrambling_f_offset(&q->seq[nsubframe], q->llr, 0, e_bits); - + ret = SRSLTE_SUCCESS; } return ret; diff --git a/lib/src/phy/phch/pdsch.c b/lib/src/phy/phch/pdsch.c index 63e7dbfa0..da0e4a6e4 100644 --- a/lib/src/phy/phch/pdsch.c +++ b/lib/src/phy/phch/pdsch.c @@ -33,6 +33,8 @@ #include #include #include +#include +#include #include "prb_dl.h" #include "srslte/phy/phch/pdsch.h" @@ -203,31 +205,23 @@ int srslte_pdsch_get(srslte_pdsch_t *q, cf_t *sf_symbols, cf_t *symbols, return srslte_pdsch_cp(q, sf_symbols, symbols, grant, lstart, subframe, false); } -int srslte_pdsch_init(srslte_pdsch_t *q, srslte_cell_t cell) -{ - return srslte_pdsch_init_multi(q, cell, 1); -} - /** Initializes the PDCCH transmitter and receiver */ -int srslte_pdsch_init_multi(srslte_pdsch_t *q, srslte_cell_t cell, uint32_t nof_rx_antennas) +int pdsch_init_multi(srslte_pdsch_t *q, uint32_t max_prb, uint32_t nof_rx_antennas, bool is_ue) { int ret = SRSLTE_ERROR_INVALID_INPUTS; int i; if (q != NULL && - srslte_cell_isvalid(&cell) && - nof_rx_antennas <= SRSLTE_MAX_PORTS) + nof_rx_antennas <= SRSLTE_MAX_PORTS) { bzero(q, sizeof(srslte_pdsch_t)); ret = SRSLTE_ERROR; - q->cell = cell; - q->max_re = q->cell.nof_prb * MAX_PDSCH_RE(q->cell.cp); + q->max_re = max_prb * MAX_PDSCH_RE(q->cell.cp); q->nof_rx_antennas = nof_rx_antennas; - INFO("Init PDSCH: %d ports %d PRBs, max_symbols: %d\n", q->cell.nof_ports, - q->cell.nof_prb, q->max_re); + INFO("Init PDSCH: %d PRBs, max_symbols: %d\n", max_prb, q->max_re); for (i = 0; i < 4; i++) { if (srslte_modem_table_lte(&q->mod[i], modulations[i])) { @@ -249,15 +243,17 @@ int srslte_pdsch_init_multi(srslte_pdsch_t *q, srslte_cell_t cell, uint32_t nof_ goto clean; } - for (i = 0; i < q->cell.nof_ports; i++) { + for (i = 0; i < SRSLTE_MAX_PORTS; i++) { q->x[i] = srslte_vec_malloc(sizeof(cf_t) * q->max_re); if (!q->x[i]) { goto clean; } - for (int j=0;jnof_rx_antennas;j++) { - q->ce[i][j] = srslte_vec_malloc(sizeof(cf_t) * q->max_re); - if (!q->ce[i][j]) { - goto clean; + if (is_ue) { + for (int j=0;jnof_rx_antennas;j++) { + q->ce[i][j] = srslte_vec_malloc(sizeof(cf_t) * q->max_re); + if (!q->ce[i][j]) { + goto clean; + } } } } @@ -267,13 +263,18 @@ int srslte_pdsch_init_multi(srslte_pdsch_t *q, srslte_cell_t cell, uint32_t nof_ goto clean; } } - - q->users = calloc(sizeof(srslte_pdsch_user_t*), 1+SRSLTE_SIRNTI); + + q->is_ue = is_ue; + q->users = calloc(sizeof(srslte_pdsch_user_t*), is_ue?1:(1+SRSLTE_SIRNTI)); if (!q->users) { perror("malloc"); goto clean; } - + + if (srslte_sequence_init(&q->tmp_seq, q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_64QAM))) { + goto clean; + } + ret = SRSLTE_SUCCESS; } clean: @@ -283,6 +284,27 @@ int srslte_pdsch_init_multi(srslte_pdsch_t *q, srslte_cell_t cell, uint32_t nof_ return ret; } +int srslte_pdsch_init_ue(srslte_pdsch_t *q, uint32_t max_prb) +{ + return pdsch_init_multi(q, max_prb, 1, true); +} + +int srslte_pdsch_init_enb(srslte_pdsch_t *q, uint32_t max_prb) +{ + return pdsch_init_multi(q, max_prb, 1, false); +} + +int srslte_pdsch_init_multi_ue(srslte_pdsch_t *q, uint32_t max_prb, uint32_t nof_rx_antennas) +{ + return pdsch_init_multi(q, max_prb, nof_rx_antennas, true); +} + +int srslte_pdsch_init_multi_enb(srslte_pdsch_t *q, uint32_t max_prb, uint32_t nof_rx_antennas) +{ + return pdsch_init_multi(q, max_prb, nof_rx_antennas, false); +} + + void srslte_pdsch_free(srslte_pdsch_t *q) { int i; @@ -292,7 +314,7 @@ void srslte_pdsch_free(srslte_pdsch_t *q) { if (q->d) { free(q->d); } - for (i = 0; i < q->cell.nof_ports; i++) { + for (i = 0; i < SRSLTE_MAX_PORTS; i++) { if (q->x[i]) { free(q->x[i]); } @@ -308,13 +330,20 @@ void srslte_pdsch_free(srslte_pdsch_t *q) { } } if (q->users) { - for (uint16_t u=0;uusers[u]) { - srslte_pdsch_free_rnti(q, u); + if (q->is_ue) { + srslte_pdsch_free_rnti(q, 0); + } else { + for (uint16_t u=0;uusers[u]) { + srslte_pdsch_free_rnti(q, u); + } } - } + } free(q->users); } + + srslte_sequence_free(&q->tmp_seq); + for (i = 0; i < 4; i++) { srslte_modem_table_free(&q->mod[i]); } @@ -325,6 +354,24 @@ void srslte_pdsch_free(srslte_pdsch_t *q) { } +int srslte_pdsch_set_cell(srslte_pdsch_t *q, srslte_cell_t cell) +{ + int ret = SRSLTE_ERROR_INVALID_INPUTS; + + if (q != NULL && + srslte_cell_isvalid(&cell)) + { + memcpy(&q->cell, &cell, sizeof(srslte_cell_t)); + q->max_re = q->cell.nof_prb * MAX_PDSCH_RE(q->cell.cp); + + INFO("PDSCH: Cell config PCI=%d, %d ports, %d PRBs, max_symbols: %d\n", q->cell.nof_ports, + q->cell.id, q->cell.nof_prb, q->max_re); + + ret = SRSLTE_SUCCESS; + } + return ret; +} + /* Configures the structure srslte_pdsch_cfg_t from the DL DCI allocation dci_msg. * If dci_msg is NULL, the grant is assumed to be already stored in cfg->grant */ @@ -353,17 +400,19 @@ int srslte_pdsch_cfg(srslte_pdsch_cfg_t *cfg, srslte_cell_t cell, srslte_ra_dl_g * to execute, so shall be called once the final C-RNTI has been allocated for the session. */ int srslte_pdsch_set_rnti(srslte_pdsch_t *q, uint16_t rnti) { - uint32_t i; - if (!q->users[rnti]) { - q->users[rnti] = calloc(1, sizeof(srslte_pdsch_user_t)); - if (q->users[rnti]) { + uint32_t i; + uint32_t rnti_idx = q->is_ue?0:rnti; + + if (!q->users[rnti_idx]) { + q->users[rnti_idx] = calloc(1, sizeof(srslte_pdsch_user_t)); + if (q->users[rnti_idx]) { for (i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) { - if (srslte_sequence_pdsch(&q->users[rnti]->seq[i], rnti, 0, 2 * i, q->cell.id, + if (srslte_sequence_pdsch(&q->users[rnti_idx]->seq[i], rnti, 0, 2 * i, q->cell.id, q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_64QAM))) { return SRSLTE_ERROR; } } - q->users[rnti]->sequence_generated = true; + q->users[rnti_idx]->sequence_generated = true; } } return SRSLTE_SUCCESS; @@ -371,12 +420,13 @@ int srslte_pdsch_set_rnti(srslte_pdsch_t *q, uint16_t rnti) { void srslte_pdsch_free_rnti(srslte_pdsch_t* q, uint16_t rnti) { - if (q->users[rnti]) { + uint32_t rnti_idx = q->is_ue?0:rnti; + if (q->users[rnti_idx]) { for (int i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) { - srslte_sequence_free(&q->users[rnti]->seq[i]); + srslte_sequence_free(&q->users[rnti_idx]->seq[i]); } - free(q->users[rnti]); - q->users[rnti] = NULL; + free(q->users[rnti_idx]); + q->users[rnti_idx] = NULL; } } @@ -395,6 +445,17 @@ int srslte_pdsch_decode(srslte_pdsch_t *q, return srslte_pdsch_decode_multi(q, cfg, softbuffer, _sf_symbols, _ce, noise_estimate, rnti, data); } +static srslte_sequence_t *get_user_sequence(srslte_pdsch_t *q, uint16_t rnti, uint32_t sf_idx, uint32_t len) +{ + uint32_t rnti_idx = q->is_ue?0:rnti; + if (q->users[rnti_idx] && q->users[rnti_idx]->sequence_generated) { + return &q->users[rnti_idx]->seq[sf_idx]; + } else { + srslte_sequence_pdsch(&q->tmp_seq, rnti, 0, 2 * sf_idx, q->cell.id, len); + return &q->tmp_seq; + } +} + /** Decodes the PDSCH from the received symbols */ int srslte_pdsch_decode_multi(srslte_pdsch_t *q, @@ -412,7 +473,7 @@ int srslte_pdsch_decode_multi(srslte_pdsch_t *q, data != NULL && cfg != NULL) { - + INFO("Decoding PDSCH SF: %d, RNTI: 0x%x, Mod %s, TBS: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d, C_prb=%d\n", cfg->sf_idx, rnti, srslte_mod_string(cfg->grant.mcs.mod), cfg->grant.mcs.tbs, cfg->nbits.nof_re, cfg->nbits.nof_bits, cfg->rv, cfg->grant.nof_prb); @@ -467,25 +528,19 @@ int srslte_pdsch_decode_multi(srslte_pdsch_t *q, * thus we don't need tot set it in the LLRs normalization */ srslte_demod_soft_demodulate_s(cfg->grant.mcs.mod, q->d, q->e, cfg->nbits.nof_re); - - /* descramble */ - if (q->users[rnti] && q->users[rnti]->sequence_generated) { - srslte_scrambling_s_offset(&q->users[rnti]->seq[cfg->sf_idx], q->e, 0, cfg->nbits.nof_bits); - } else { - srslte_sequence_t seq; - if (srslte_sequence_pdsch(&seq, rnti, 0, 2 * cfg->sf_idx, q->cell.id, cfg->nbits.nof_bits)) { - return SRSLTE_ERROR; - } - srslte_scrambling_s_offset(&seq, q->e, 0, cfg->nbits.nof_bits); - srslte_sequence_free(&seq); - } + + // Generate scrambling sequence if not pre-generated + srslte_sequence_t *seq = get_user_sequence(q, rnti, cfg->sf_idx, cfg->nbits.nof_bits); + + // Run scrambling + srslte_scrambling_s_offset(seq, q->e, 0, cfg->nbits.nof_bits); if (SRSLTE_VERBOSE_ISDEBUG()) { DEBUG("SAVED FILE llr.dat: LLR estimates after demodulation and descrambling\n",0); srslte_vec_save_file("llr.dat", q->e, cfg->nbits.nof_bits*sizeof(int16_t)); } - return srslte_dlsch_decode(&q->dl_sch, cfg, softbuffer, q->e, data); + return srslte_dlsch_decode(&q->dl_sch, cfg, softbuffer, q->e, data); } else { return SRSLTE_ERROR_INVALID_INPUTS; @@ -538,18 +593,11 @@ int srslte_pdsch_encode(srslte_pdsch_t *q, return SRSLTE_ERROR; } - /* scramble */ - if (q->users[rnti] && q->users[rnti]->sequence_generated) { - srslte_scrambling_bytes(&q->users[rnti]->seq[cfg->sf_idx], (uint8_t*) q->e, cfg->nbits.nof_bits); - } else { - srslte_sequence_t seq; - if (srslte_sequence_pdsch(&seq, rnti, 0, 2 * cfg->sf_idx, q->cell.id, cfg->nbits.nof_bits)) { - return SRSLTE_ERROR; - } - srslte_scrambling_bytes(&seq, (uint8_t*) q->e, cfg->nbits.nof_bits); - srslte_sequence_free(&seq); - } - + // Generate scrambling sequence if not pre-generated + srslte_sequence_t *seq = get_user_sequence(q, rnti, cfg->sf_idx, cfg->nbits.nof_bits); + + srslte_scrambling_bytes(seq, (uint8_t*) q->e, cfg->nbits.nof_bits); + srslte_mod_modulate_bytes(&q->mod[cfg->grant.mcs.mod], (uint8_t*) q->e, q->d, cfg->nbits.nof_bits); /* TODO: only diversity supported */ diff --git a/lib/src/phy/phch/phich.c b/lib/src/phy/phch/phich.c index 7de2f5d37..7e7f0e8c8 100644 --- a/lib/src/phy/phch/phich.c +++ b/lib/src/phy/phch/phich.c @@ -32,6 +32,7 @@ #include #include #include +#include #include "srslte/phy/phch/regs.h" #include "srslte/phy/phch/phich.h" @@ -67,37 +68,27 @@ void srslte_phich_reset(srslte_phich_t *q, cf_t *slot_symbols[SRSLTE_MAX_PORTS]) } } -int srslte_phich_init(srslte_phich_t *q, srslte_regs_t *regs, srslte_cell_t cell) +int srslte_phich_init(srslte_phich_t *q) { - return srslte_phich_init_multi(q, regs, cell, 1); + return srslte_phich_init_multi(q, 1); } /** Initializes the phich channel receiver */ -int srslte_phich_init_multi(srslte_phich_t *q, srslte_regs_t *regs, srslte_cell_t cell, uint32_t nof_rx_antennas) +int srslte_phich_init_multi(srslte_phich_t *q, uint32_t nof_rx_antennas) { int ret = SRSLTE_ERROR_INVALID_INPUTS; - if (q != NULL && - regs != NULL && - srslte_cell_isvalid(&cell)) + if (q != NULL) { bzero(q, sizeof(srslte_phich_t)); ret = SRSLTE_ERROR; - q->cell = cell; - q->regs = regs; - q->nof_rx_antennas = nof_rx_antennas; + q->nof_rx_antennas = nof_rx_antennas; if (srslte_modem_table_lte(&q->mod, SRSLTE_MOD_BPSK)) { goto clean; } - - for (int nsf = 0; nsf < SRSLTE_NSUBFRAMES_X_FRAME; nsf++) { - if (srslte_sequence_phich(&q->seq[nsf], 2 * nsf, q->cell.id)) { - goto clean; - } - } ret = SRSLTE_SUCCESS; } clean: @@ -114,9 +105,34 @@ void srslte_phich_free(srslte_phich_t *q) { srslte_modem_table_free(&q->mod); bzero(q, sizeof(srslte_phich_t)); - } +int srslte_phich_set_cell(srslte_phich_t *q, srslte_regs_t *regs, srslte_cell_t cell) +{ + int ret = SRSLTE_ERROR_INVALID_INPUTS; + + if (q != NULL && + regs != NULL && + srslte_cell_isvalid(&cell)) + { + + q->regs = regs; + + if (cell.id != q->cell.id || q->cell.nof_prb == 0) { + memcpy(&q->cell, &cell, sizeof(srslte_cell_t)); + for (int nsf = 0; nsf < SRSLTE_NSUBFRAMES_X_FRAME; nsf++) { + if (srslte_sequence_phich(&q->seq[nsf], 2 * nsf, q->cell.id)) { + return SRSLTE_ERROR; + } + } + } + ret = SRSLTE_SUCCESS; + } + return ret; +} + + + /* Computes n_group and n_seq according to Section 9.1.2 in 36.213 */ void srslte_phich_calc(srslte_phich_t *q, uint32_t n_prb_lowest, uint32_t n_dmrs, uint32_t *ngroup, uint32_t *nseq) diff --git a/lib/src/phy/phch/prach.c b/lib/src/phy/phch/prach.c index 5a2169fd9..f2ddd48db 100644 --- a/lib/src/phy/phch/prach.c +++ b/lib/src/phy/phch/prach.c @@ -26,6 +26,7 @@ #include #include +#include #include "srslte/phy/common/phy_common.h" #include "srslte/phy/phch/prach.h" @@ -61,6 +62,8 @@ uint32_t prach_Tseq[5] = {24576, 24576, 2*24576, 2*24576, 4096}; // Table 5.7.2-2 - N_cs values for unrestricted sets uint32_t prach_Ncs_unrestricted[16] = {0,13,15,18,22,26,32,38,46,59,76,93,119,167,279,419}; +#define MAX_N_zc 839 + // Table 5.7.2-2 - N_cs values for restricted sets uint32_t prach_Ncs_restricted[15] = {15,18,22,26,32,38,46,55,68,82,100,128,158,202,237}; @@ -328,7 +331,7 @@ int srslte_prach_gen_seqs(srslte_prach_t *p) int srslte_prach_init_cfg(srslte_prach_t *p, srslte_prach_cfg_t *cfg, uint32_t nof_prb) { - return srslte_prach_init(p, + return srslte_prach_set_cell(p, srslte_symbol_sz(nof_prb), cfg->config_idx, cfg->root_seq_idx, @@ -336,28 +339,95 @@ int srslte_prach_init_cfg(srslte_prach_t *p, srslte_prach_cfg_t *cfg, uint32_t n cfg->zero_corr_zone); } -int srslte_prach_init(srslte_prach_t *p, - uint32_t N_ifft_ul, - uint32_t config_idx, - uint32_t root_seq_index, - bool high_speed_flag, - uint32_t zero_corr_zone_config) +int srslte_prach_init(srslte_prach_t *p, uint32_t max_N_ifft_ul) +{ + int ret = SRSLTE_ERROR; + if(p != NULL && + max_N_ifft_ul < 2049) + { + bzero(p, sizeof(srslte_prach_t)); + + p->max_N_ifft_ul = max_N_ifft_ul; + + // Set up containers + p->prach_bins = srslte_vec_malloc(sizeof(cf_t)*MAX_N_zc); + p->corr_spec = srslte_vec_malloc(sizeof(cf_t)*MAX_N_zc); + p->corr = srslte_vec_malloc(sizeof(float)*MAX_N_zc); + + // Set up ZC FFTS + if(srslte_dft_plan(&p->zc_fft, MAX_N_zc, SRSLTE_DFT_FORWARD, SRSLTE_DFT_COMPLEX)){ + return SRSLTE_ERROR; + } + srslte_dft_plan_set_mirror(&p->zc_fft, false); + srslte_dft_plan_set_norm(&p->zc_fft, true); + + if(srslte_dft_plan(&p->zc_ifft, MAX_N_zc, SRSLTE_DFT_BACKWARD, SRSLTE_DFT_COMPLEX)){ + return SRSLTE_ERROR; + } + srslte_dft_plan_set_mirror(&p->zc_ifft, false); + srslte_dft_plan_set_norm(&p->zc_ifft, false); + + uint32_t fft_size_alloc = max_N_ifft_ul * DELTA_F/DELTA_F_RA; + + p->ifft_in = (cf_t*)srslte_vec_malloc(fft_size_alloc*sizeof(cf_t)); + p->ifft_out = (cf_t*)srslte_vec_malloc(fft_size_alloc*sizeof(cf_t)); + if(srslte_dft_plan(&p->ifft, fft_size_alloc, SRSLTE_DFT_BACKWARD, SRSLTE_DFT_COMPLEX)) { + fprintf(stderr, "Error creating DFT plan\n"); + return -1; + } + srslte_dft_plan_set_mirror(&p->ifft, true); + srslte_dft_plan_set_norm(&p->ifft, true); + + if(srslte_dft_plan(&p->fft, fft_size_alloc, SRSLTE_DFT_FORWARD, SRSLTE_DFT_COMPLEX)){ + fprintf(stderr, "Error creating DFT plan\n"); + return -1; + } + + p->signal_fft = srslte_vec_malloc(sizeof(cf_t)*fft_size_alloc); + if (!p->signal_fft) { + fprintf(stderr, "Error allocating memory\n"); + return -1; + } + + srslte_dft_plan_set_mirror(&p->fft, true); + srslte_dft_plan_set_norm(&p->fft, false); + + ret = SRSLTE_SUCCESS; + } else { + fprintf(stderr, "Invalid parameters\n"); + } + + return ret; +} + + +int srslte_prach_set_cell(srslte_prach_t *p, + uint32_t N_ifft_ul, + uint32_t config_idx, + uint32_t root_seq_index, + bool high_speed_flag, + uint32_t zero_corr_zone_config) { int ret = SRSLTE_ERROR; if(p != NULL && N_ifft_ul < 2049 && - config_idx < 64 && + config_idx < 64 && root_seq_index < MAX_ROOTS) { + if (N_ifft_ul > p->max_N_ifft_ul) { + fprintf(stderr, "PRACH: Error in set_cell(): N_ifft_ul must be lower or equal max_N_ifft_ul in init()\n"); + return -1; + } + uint32_t preamble_format = srslte_prach_get_preamble_format(config_idx); - p->config_idx = config_idx; + p->config_idx = config_idx; p->f = preamble_format; p->rsi = root_seq_index; p->hs = high_speed_flag; p->zczc = zero_corr_zone_config; - p->detect_factor = PRACH_DETECT_FACTOR; - - + p->detect_factor = PRACH_DETECT_FACTOR; + + // Determine N_zc and N_cs if(4 == preamble_format){ if (p->zczc < 7) { @@ -368,43 +438,33 @@ int srslte_prach_init(srslte_prach_t *p, return SRSLTE_ERROR; } }else{ - p->N_zc = 839; + p->N_zc = MAX_N_zc; if(p->hs){ if (p->zczc < 15) { p->N_cs = prach_Ncs_restricted[p->zczc]; } else { fprintf(stderr, "Invalid zeroCorrelationZoneConfig=%d for restricted set\n", p->zczc); return SRSLTE_ERROR; - } + } }else{ if (p->zczc < 16) { p->N_cs = prach_Ncs_unrestricted[p->zczc]; } else { fprintf(stderr, "Invalid zeroCorrelationZoneConfig=%d\n", p->zczc); return SRSLTE_ERROR; - } + } } } - - // Set up containers - p->prach_bins = srslte_vec_malloc(sizeof(cf_t)*p->N_zc); - p->corr_spec = srslte_vec_malloc(sizeof(cf_t)*p->N_zc); - p->corr = srslte_vec_malloc(sizeof(float)*p->N_zc); // Set up ZC FFTS - p->zc_fft = (srslte_dft_plan_t*)srslte_vec_malloc(sizeof(srslte_dft_plan_t)); - if(srslte_dft_plan(p->zc_fft, p->N_zc, SRSLTE_DFT_FORWARD, SRSLTE_DFT_COMPLEX)){ - return SRSLTE_ERROR; + if (p->N_zc != MAX_N_zc) { + if(srslte_dft_replan(&p->zc_fft, p->N_zc)){ + return SRSLTE_ERROR; + } + if(srslte_dft_replan(&p->zc_ifft, p->N_zc)){ + return SRSLTE_ERROR; + } } - srslte_dft_plan_set_mirror(p->zc_fft, false); - srslte_dft_plan_set_norm(p->zc_fft, true); - - p->zc_ifft = (srslte_dft_plan_t*)srslte_vec_malloc(sizeof(srslte_dft_plan_t)); - if(srslte_dft_plan(p->zc_ifft, p->N_zc, SRSLTE_DFT_BACKWARD, SRSLTE_DFT_COMPLEX)){ - return SRSLTE_ERROR; - } - srslte_dft_plan_set_mirror(p->zc_ifft, false); - srslte_dft_plan_set_norm(p->zc_ifft, false); // Generate our 64 sequences p->N_roots = 0; @@ -412,9 +472,9 @@ int srslte_prach_init(srslte_prach_t *p, // Generate sequence FFTs for(int i=0;izc_fft, p->seqs[i], p->dft_seqs[i]); + srslte_dft_run(&p->zc_fft, p->seqs[i], p->dft_seqs[i]); } - + // Create our FFT objects and buffers p->N_ifft_ul = N_ifft_ul; if(4 == preamble_format){ @@ -422,47 +482,31 @@ int srslte_prach_init(srslte_prach_t *p, }else{ p->N_ifft_prach = p->N_ifft_ul * DELTA_F/DELTA_F_RA; } - + /* The deadzone specifies the number of samples at the end of the correlation window * that will be considered as belonging to the next preamble */ - p->deadzone = 0; + p->deadzone = 0; /* if(p->N_cs != 0) { float samp_rate=15000*p->N_ifft_ul; p->deadzone = (uint32_t) ceil((float) samp_rate/((float) p->N_zc*subcarrier_spacing)); }*/ - p->ifft_in = (cf_t*)srslte_vec_malloc(p->N_ifft_prach*sizeof(cf_t)); - p->ifft_out = (cf_t*)srslte_vec_malloc(p->N_ifft_prach*sizeof(cf_t)); - p->ifft = (srslte_dft_plan_t*)srslte_vec_malloc(sizeof(srslte_dft_plan_t)); - if(srslte_dft_plan(p->ifft, p->N_ifft_prach, SRSLTE_DFT_BACKWARD, SRSLTE_DFT_COMPLEX)) { + if(srslte_dft_replan(&p->ifft, p->N_ifft_prach)) { fprintf(stderr, "Error creating DFT plan\n"); return -1; } - srslte_dft_plan_set_mirror(p->ifft, true); - srslte_dft_plan_set_norm(p->ifft, true); - - p->fft = (srslte_dft_plan_t*)srslte_vec_malloc(sizeof(srslte_dft_plan_t)); - if(srslte_dft_plan(p->fft, p->N_ifft_prach, SRSLTE_DFT_FORWARD, SRSLTE_DFT_COMPLEX)){ + if(srslte_dft_replan(&p->fft, p->N_ifft_prach)){ fprintf(stderr, "Error creating DFT plan\n"); return -1; } - - p->signal_fft = srslte_vec_malloc(sizeof(cf_t)*p->N_ifft_prach); - if (!p->signal_fft) { - fprintf(stderr, "Error allocating memory\n"); - return -1; - } - - srslte_dft_plan_set_mirror(p->fft, true); - srslte_dft_plan_set_norm(p->fft, false); p->N_seq = prach_Tseq[p->f]*p->N_ifft_ul/2048; p->N_cp = prach_Tcp[p->f]*p->N_ifft_ul/2048; p->T_seq = prach_Tseq[p->f]*SRSLTE_LTE_TS; p->T_tot = (prach_Tseq[p->f]+prach_Tcp[p->f])*SRSLTE_LTE_TS; - + ret = SRSLTE_SUCCESS; } else { fprintf(stderr, "Invalid parameters\n"); @@ -500,7 +544,7 @@ int srslte_prach_gen(srslte_prach_t *p, memcpy(&p->ifft_in[begin], p->dft_seqs[seq_index], p->N_zc * sizeof(cf_t)); memset(&p->ifft_in[begin+p->N_zc], 0, (p->N_ifft_prach - begin - p->N_zc) * sizeof(cf_t)); - srslte_dft_run(p->ifft, p->ifft_in, p->ifft_out); + srslte_dft_run(&p->ifft, p->ifft_in, p->ifft_out); // Copy CP into buffer memcpy(signal, &p->ifft_out[p->N_ifft_prach-p->N_cp], p->N_cp*sizeof(cf_t)); @@ -552,7 +596,7 @@ int srslte_prach_detect_offset(srslte_prach_t *p, } // FFT incoming signal - srslte_dft_run(p->fft, signal, p->signal_fft); + srslte_dft_run(&p->fft, signal, p->signal_fft); *n_indices = 0; @@ -569,7 +613,7 @@ int srslte_prach_detect_offset(srslte_prach_t *p, srslte_vec_prod_conj_ccc(p->prach_bins, root_spec, p->corr_spec, p->N_zc); - srslte_dft_run(p->zc_ifft, p->corr_spec, p->corr_spec); + srslte_dft_run(&p->zc_ifft, p->corr_spec, p->corr_spec); srslte_vec_abs_square_cf(p->corr_spec, p->corr, p->N_zc); @@ -632,16 +676,12 @@ int srslte_prach_free(srslte_prach_t *p) { free(p->prach_bins); free(p->corr_spec); free(p->corr); - srslte_dft_plan_free(p->ifft); - free(p->ifft); + srslte_dft_plan_free(&p->ifft); free(p->ifft_in); free(p->ifft_out); - srslte_dft_plan_free(p->fft); - free(p->fft); - srslte_dft_plan_free(p->zc_fft); - free(p->zc_fft); - srslte_dft_plan_free(p->zc_ifft); - free(p->zc_ifft); + srslte_dft_plan_free(&p->fft); + srslte_dft_plan_free(&p->zc_fft); + srslte_dft_plan_free(&p->zc_ifft); if (p->signal_fft) { free(p->signal_fft); diff --git a/lib/src/phy/phch/pucch.c b/lib/src/phy/phch/pucch.c index 6a889b89c..4bc834ab9 100644 --- a/lib/src/phy/phch/pucch.c +++ b/lib/src/phy/phch/pucch.c @@ -417,43 +417,30 @@ void srslte_pucch_set_threshold(srslte_pucch_t *q, float format1, float format1a } /** Initializes the PDCCH transmitter and receiver */ -int srslte_pucch_init(srslte_pucch_t *q, srslte_cell_t cell) { +int srslte_pucch_init(srslte_pucch_t *q) { int ret = SRSLTE_ERROR_INVALID_INPUTS; - if (q != NULL && srslte_cell_isvalid(&cell)) { + if (q != NULL) { ret = SRSLTE_ERROR; bzero(q, sizeof(srslte_pucch_t)); - q->cell = cell; - - srslte_pucch_cfg_default(&q->pucch_cfg); - if (srslte_modem_table_lte(&q->mod, SRSLTE_MOD_QPSK)) { return SRSLTE_ERROR; } - - // Precompute group hopping values u. - if (srslte_group_hopping_f_gh(q->f_gh, q->cell.id)) { - return SRSLTE_ERROR; - } - - if (srslte_pucch_n_cs_cell(q->cell, q->n_cs_cell)) { - return SRSLTE_ERROR; - } - + q->users = calloc(sizeof(srslte_pucch_user_t*), 1+SRSLTE_SIRNTI); if (!q->users) { perror("malloc"); - return SRSLTE_ERROR; + goto clean_exit; } srslte_uci_cqi_pucch_init(&q->cqi); - - q->z = srslte_vec_malloc(sizeof(cf_t)*SRSLTE_PUCCH_MAX_SYMBOLS); - q->z_tmp = srslte_vec_malloc(sizeof(cf_t)*SRSLTE_PUCCH_MAX_SYMBOLS); - q->ce = srslte_vec_malloc(sizeof(cf_t)*SRSLTE_PUCCH_MAX_SYMBOLS); ret = SRSLTE_SUCCESS; } +clean_exit: + if (ret == SRSLTE_ERROR) { + srslte_pucch_free(q); + } return ret; } @@ -464,20 +451,36 @@ void srslte_pucch_free(srslte_pucch_t *q) { } free(q->users); } - if (q->z) { - free(q->z); - } - if (q->z_tmp) { - free(q->z_tmp); - } - if (q->ce) { - free(q->ce); - } - + srslte_modem_table_free(&q->mod); bzero(q, sizeof(srslte_pucch_t)); } +int srslte_pucch_set_cell(srslte_pucch_t *q, srslte_cell_t cell) { + int ret = SRSLTE_ERROR_INVALID_INPUTS; + if (q != NULL && srslte_cell_isvalid(&cell)) { + + srslte_pucch_cfg_default(&q->pucch_cfg); + + if (cell.id != q->cell.id || q->cell.nof_prb == 0) { + memcpy(&q->cell, &cell, sizeof(srslte_cell_t)); + + // Precompute group hopping values u. + if (srslte_group_hopping_f_gh(q->f_gh, q->cell.id)) { + return SRSLTE_ERROR; + } + + if (srslte_pucch_n_cs_cell(q->cell, q->n_cs_cell)) { + return SRSLTE_ERROR; + } + } + + ret = SRSLTE_SUCCESS; + } + return ret; +} + + void srslte_pucch_clear_rnti(srslte_pucch_t *q, uint16_t rnti) { if (q->users[rnti]) { for (int i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) { @@ -496,6 +499,7 @@ int srslte_pucch_set_crnti(srslte_pucch_t *q, uint16_t rnti) { // Precompute scrambling sequence for pucch format 2 if (srslte_sequence_pucch(&q->users[rnti]->seq_f2[sf_idx], rnti, 2*sf_idx, q->cell.id)) { fprintf(stderr, "Error computing PUCCH Format 2 scrambling sequence\n"); + srslte_pucch_clear_rnti(q, rnti); return SRSLTE_ERROR; } } diff --git a/lib/src/phy/phch/pusch.c b/lib/src/phy/phch/pusch.c index 3fbb7627e..c3ce03edc 100644 --- a/lib/src/phy/phch/pusch.c +++ b/lib/src/phy/phch/pusch.c @@ -32,6 +32,8 @@ #include #include #include +#include +#include #include "srslte/phy/ch_estimation/refsignal_ul.h" #include "srslte/phy/phch/pusch.h" @@ -185,22 +187,18 @@ int pusch_get(srslte_pusch_t *q, srslte_ra_ul_grant_t *grant, cf_t *input, cf_t /** Initializes the PDCCH transmitter and receiver */ -int srslte_pusch_init(srslte_pusch_t *q, srslte_cell_t cell) { +int pusch_init(srslte_pusch_t *q, uint32_t max_prb, bool is_ue) { int ret = SRSLTE_ERROR_INVALID_INPUTS; int i; - if (q != NULL && - srslte_cell_isvalid(&cell)) + if (q != NULL) { bzero(q, sizeof(srslte_pusch_t)); ret = SRSLTE_ERROR; - - q->cell = cell; - q->max_re = q->cell.nof_prb * MAX_PUSCH_RE(q->cell.cp); + q->max_re = max_prb * MAX_PUSCH_RE(SRSLTE_CP_NORM); - INFO("Init PUSCH: %d ports %d PRBs, max_symbols: %d\n", q->cell.nof_ports, - q->cell.nof_prb, q->max_re); + INFO("Init PUSCH: %d PRBs\n", max_prb); for (i = 0; i < 4; i++) { if (srslte_modem_table_lte(&q->mod[i], modulations[i])) { @@ -208,26 +206,26 @@ int srslte_pusch_init(srslte_pusch_t *q, srslte_cell_t cell) { } srslte_modem_table_bytes(&q->mod[i]); } - - q->users = calloc(sizeof(srslte_pusch_user_t*), 1+SRSLTE_SIRNTI); + + q->is_ue = is_ue; + + q->users = calloc(sizeof(srslte_pusch_user_t*), q->is_ue?1:(1+SRSLTE_SIRNTI)); if (!q->users) { perror("malloc"); goto clean; } - /* Precompute sequence for type2 frequency hopping */ - if (srslte_sequence_LTE_pr(&q->seq_type2_fo, 210, q->cell.id)) { - fprintf(stderr, "Error initiating type2 frequency hopping sequence\n"); - goto clean; + if (srslte_sequence_init(&q->tmp_seq, q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_64QAM))) { + goto clean; } srslte_sch_init(&q->ul_sch); - - if (srslte_dft_precoding_init(&q->dft_precoding, cell.nof_prb)) { + + if (srslte_dft_precoding_init(&q->dft_precoding, max_prb, is_ue)) { fprintf(stderr, "Error initiating DFT transform precoding\n"); goto clean; } - + // Allocate int16 for reception (LLRs). Buffer casted to uint8_t for transmission q->q = srslte_vec_malloc(sizeof(int16_t) * q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_64QAM)); if (!q->q) { @@ -244,9 +242,11 @@ int srslte_pusch_init(srslte_pusch_t *q, srslte_cell_t cell) { goto clean; } - q->ce = srslte_vec_malloc(sizeof(cf_t) * q->max_re); - if (!q->ce) { - goto clean; + if (!q->is_ue) { + q->ce = srslte_vec_malloc(sizeof(cf_t) * q->max_re); + if (!q->ce) { + goto clean; + } } q->z = srslte_vec_malloc(sizeof(cf_t) * q->max_re); if (!q->z) { @@ -262,6 +262,14 @@ int srslte_pusch_init(srslte_pusch_t *q, srslte_cell_t cell) { return ret; } +int srslte_pusch_init_ue(srslte_pusch_t *q, uint32_t max_prb) { + return pusch_init(q, max_prb, true); +} + +int srslte_pusch_init_enb(srslte_pusch_t *q, uint32_t max_prb) { + return pusch_init(q, max_prb, false); +} + void srslte_pusch_free(srslte_pusch_t *q) { int i; @@ -284,13 +292,20 @@ void srslte_pusch_free(srslte_pusch_t *q) { srslte_dft_precoding_free(&q->dft_precoding); if (q->users) { - for (int rnti=0;rntiis_ue) { + srslte_pusch_clear_rnti(q, 0); + } else { + for (int rnti=0;rntiusers); } + srslte_sequence_free(&q->seq_type2_fo); + srslte_sequence_free(&q->tmp_seq); + for (i = 0; i < 4; i++) { srslte_modem_table_free(&q->mod[i]); } @@ -300,6 +315,33 @@ void srslte_pusch_free(srslte_pusch_t *q) { } +int srslte_pusch_set_cell(srslte_pusch_t *q, srslte_cell_t cell) { + int ret = SRSLTE_ERROR_INVALID_INPUTS; + + if (q != NULL && srslte_cell_isvalid(&cell)) + { + + q->max_re = cell.nof_prb * MAX_PUSCH_RE(q->cell.cp); + + INFO("PUSCH: Cell config PCI=5d, %d ports %d PRBs, max_symbols: %d\n", + q->cell.id, q->cell.nof_ports, q->cell.nof_prb, q->max_re); + + if (q->cell.id != cell.id || q->cell.nof_prb == 0) { + memcpy(&q->cell, &cell, sizeof(srslte_cell_t)); + /* Precompute sequence for type2 frequency hopping */ + if (srslte_sequence_LTE_pr(&q->seq_type2_fo, 210, q->cell.id)) { + fprintf(stderr, "Error initiating type2 frequency hopping sequence\n"); + return SRSLTE_ERROR; + } + + } + ret = SRSLTE_SUCCESS; + } + return ret; +} + + + /* Configures the structure srslte_pusch_cfg_t from the UL DCI allocation dci_msg. * If dci_msg is NULL, the grant is assumed to be already stored in cfg->grant */ @@ -391,29 +433,48 @@ int srslte_pusch_cfg(srslte_pusch_t *q, * For the connection procedure, use srslte_pusch_encode() functions */ int srslte_pusch_set_rnti(srslte_pusch_t *q, uint16_t rnti) { uint32_t i; + + uint32_t rnti_idx = q->is_ue?0:rnti; - if (!q->users[rnti]) { - q->users[rnti] = malloc(sizeof(srslte_pusch_user_t)); - if (q->users[rnti]) { + if (!q->users[rnti_idx]) { + q->users[rnti_idx] = calloc(1, sizeof(srslte_pusch_user_t)); + if (q->users[rnti_idx]) { for (i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) { - if (srslte_sequence_pusch(&q->users[rnti]->seq[i], rnti, 2 * i, q->cell.id, + if (srslte_sequence_pusch(&q->users[rnti_idx]->seq[i], rnti, 2 * i, q->cell.id, q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_64QAM))) { - return SRSLTE_ERROR; + fprintf(stderr, "Error initializing PUSCH scrambling sequence\n"); + srslte_pusch_clear_rnti(q, rnti); + return SRSLTE_ERROR; } } - q->users[rnti]->sequences_generated = true; + q->users[rnti_idx]->sequence_generated = true; } } return SRSLTE_SUCCESS; } void srslte_pusch_clear_rnti(srslte_pusch_t *q, uint16_t rnti) { - if (q->users[rnti]) { + + uint32_t rnti_idx = q->is_ue?0:rnti; + + if (q->users[rnti_idx]) { for (int i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) { - srslte_sequence_free(&q->users[rnti]->seq[i]); + srslte_sequence_free(&q->users[rnti_idx]->seq[i]); } - free(q->users[rnti]); - q->users[rnti] = NULL; + free(q->users[rnti_idx]); + q->users[rnti_idx] = NULL; + } +} + + +static srslte_sequence_t *get_user_sequence(srslte_pusch_t *q, uint16_t rnti, uint32_t sf_idx, uint32_t len) +{ + uint32_t rnti_idx = q->is_ue?0:rnti; + if (q->users[rnti_idx] && q->users[rnti_idx]->sequence_generated) { + return &q->users[rnti_idx]->seq[sf_idx]; + } else { + srslte_sequence_pusch(&q->tmp_seq, rnti, 2 * sf_idx, q->cell.id, len); + return &q->tmp_seq; } } @@ -445,17 +506,12 @@ int srslte_pusch_encode(srslte_pusch_t *q, srslte_pusch_cfg_t *cfg, srslte_softb return SRSLTE_ERROR; } - if (q->users[rnti] && q->users[rnti]->sequences_generated) { - srslte_scrambling_bytes(&q->users[rnti]->seq[cfg->sf_idx], (uint8_t*) q->q, cfg->nbits.nof_bits); - } else { - srslte_sequence_t seq; - if (srslte_sequence_pusch(&seq, rnti, 2 * cfg->sf_idx, q->cell.id, cfg->nbits.nof_bits)) { - return SRSLTE_ERROR; - } - srslte_scrambling_bytes(&seq, (uint8_t*) q->q, cfg->nbits.nof_bits); - srslte_sequence_free(&seq); - } - + // Generate scrambling sequence if not pre-generated + srslte_sequence_t *seq = get_user_sequence(q, rnti, cfg->sf_idx, cfg->nbits.nof_bits); + + // Run scrambling + srslte_scrambling_bytes(seq, (uint8_t*) q->q, cfg->nbits.nof_bits); + // Correct UCI placeholder/repetition bits uint8_t *d = q->q; for (int i = 0; i < q->ul_sch.nof_ri_ack_bits; i++) { @@ -528,23 +584,14 @@ int srslte_pusch_decode(srslte_pusch_t *q, srslte_predecoding_single(q->d, q->ce, q->z, cfg->nbits.nof_re, noise_estimate); // DFT predecoding - srslte_dft_predecoding(&q->dft_precoding, q->z, q->d, cfg->grant.L_prb, cfg->nbits.nof_symb); + srslte_dft_precoding(&q->dft_precoding, q->z, q->d, cfg->grant.L_prb, cfg->nbits.nof_symb); // Soft demodulation srslte_demod_soft_demodulate_s(cfg->grant.mcs.mod, q->d, q->q, cfg->nbits.nof_re); - srslte_sequence_t *seq = NULL; + // Generate scrambling sequence if not pre-generated + srslte_sequence_t *seq = get_user_sequence(q, rnti, cfg->sf_idx, cfg->nbits.nof_bits); - // Create sequence if does not exist - if (q->users[rnti] && q->users[rnti]->sequences_generated) { - seq = &q->users[rnti]->seq[cfg->sf_idx]; - } else { - seq = &q->tmp_seq; - if (srslte_sequence_pusch(seq, rnti, 2 * cfg->sf_idx, q->cell.id, cfg->nbits.nof_bits)) { - return SRSLTE_ERROR; - } - } - // Decode RI/HARQ bits before descrambling if (srslte_ulsch_uci_decode_ri_ack(&q->ul_sch, cfg, softbuffer, q->q, seq->c, uci_data)) { fprintf(stderr, "Error decoding RI/HARQ bits\n"); @@ -554,11 +601,7 @@ int srslte_pusch_decode(srslte_pusch_t *q, // Descrambling srslte_scrambling_s_offset(seq, q->q, 0, cfg->nbits.nof_bits); - if (!(q->users[rnti] && q->users[rnti]->sequences_generated)) { - srslte_sequence_free(seq); - } - - return srslte_ulsch_uci_decode(&q->ul_sch, cfg, softbuffer, q->q, q->g, data, uci_data); + return srslte_ulsch_uci_decode(&q->ul_sch, cfg, softbuffer, q->q, q->g, data, uci_data); } else { return SRSLTE_ERROR_INVALID_INPUTS; } diff --git a/lib/src/phy/phch/sch.c b/lib/src/phy/phch/sch.c index dceab2506..b2c008e6c 100644 --- a/lib/src/phy/phch/sch.c +++ b/lib/src/phy/phch/sch.c @@ -455,7 +455,7 @@ static int decode_tb(srslte_sch_t *q, e_bits != NULL && cb_segm != NULL) { - + if (cb_segm->tbs == 0 || cb_segm->C == 0) { return SRSLTE_SUCCESS; } @@ -476,8 +476,8 @@ static int decode_tb(srslte_sch_t *q, data[cb_segm->tbs/8+0] = 0; data[cb_segm->tbs/8+1] = 0; - data[cb_segm->tbs/8+2] = 0; - + data[cb_segm->tbs/8+2] = 0; + // Process Codeblocks in groups of equal CB size to parallelize according to SRSLTE_TDEC_NPAR for (uint32_t i=0;icb_segm, - cfg->grant.Qm, cfg->rv, cfg->nbits.nof_bits, + cfg->grant.Qm, cfg->rv, cfg->nbits.nof_bits, e_bits, data); } @@ -538,7 +538,7 @@ int srslte_dlsch_encode(srslte_sch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbuf { return encode_tb(q, softbuffer, &cfg->cb_segm, - cfg->grant.Qm, cfg->rv, cfg->nbits.nof_bits, + cfg->grant.Qm, cfg->rv, cfg->nbits.nof_bits, data, e_bits); } diff --git a/lib/src/phy/phch/sequences.c b/lib/src/phy/phch/sequences.c index 2816709b4..23ac410c4 100644 --- a/lib/src/phy/phch/sequences.c +++ b/lib/src/phy/phch/sequences.c @@ -33,7 +33,6 @@ * 36.211 6.6.1 */ int srslte_sequence_pbch(srslte_sequence_t *seq, srslte_cp_t cp, uint32_t cell_id) { - bzero(seq, sizeof(srslte_sequence_t)); return srslte_sequence_LTE_pr(seq, SRSLTE_CP_ISNORM(cp)?1920:1728, cell_id); } @@ -41,7 +40,6 @@ int srslte_sequence_pbch(srslte_sequence_t *seq, srslte_cp_t cp, uint32_t cell_i * 36.211 6.7.1 */ int srslte_sequence_pcfich(srslte_sequence_t *seq, uint32_t nslot, uint32_t cell_id) { - bzero(seq, sizeof(srslte_sequence_t)); return srslte_sequence_LTE_pr(seq, 32, (nslot/2+1) * (2*cell_id + 1) * 512 + cell_id); } @@ -50,7 +48,6 @@ int srslte_sequence_pcfich(srslte_sequence_t *seq, uint32_t nslot, uint32_t cell * 36.211 6.9.1 */ int srslte_sequence_phich(srslte_sequence_t *seq, uint32_t nslot, uint32_t cell_id) { - bzero(seq, sizeof(srslte_sequence_t)); return srslte_sequence_LTE_pr(seq, 12, (nslot/2+1) * (2*cell_id + 1) * 512 + cell_id); } @@ -58,7 +55,6 @@ int srslte_sequence_phich(srslte_sequence_t *seq, uint32_t nslot, uint32_t cell_ * 36.211 6.8.2 */ int srslte_sequence_pdcch(srslte_sequence_t *seq, uint32_t nslot, uint32_t cell_id, uint32_t len) { - bzero(seq, sizeof(srslte_sequence_t)); return srslte_sequence_LTE_pr(seq, len, (nslot/2) * 512 + cell_id); } @@ -66,7 +62,6 @@ int srslte_sequence_pdcch(srslte_sequence_t *seq, uint32_t nslot, uint32_t cell_ * 36.211 6.3.1 */ int srslte_sequence_pdsch(srslte_sequence_t *seq, uint16_t rnti, int q, uint32_t nslot, uint32_t cell_id, uint32_t len) { - bzero(seq, sizeof(srslte_sequence_t)); return srslte_sequence_LTE_pr(seq, len, (rnti<<14) + (q<<13) + ((nslot/2)<<9) + cell_id); } @@ -74,7 +69,6 @@ int srslte_sequence_pdsch(srslte_sequence_t *seq, uint16_t rnti, int q, uint32_t * 36.211 5.3.1 */ int srslte_sequence_pusch(srslte_sequence_t *seq, uint16_t rnti, uint32_t nslot, uint32_t cell_id, uint32_t len) { - bzero(seq, sizeof(srslte_sequence_t)); return srslte_sequence_LTE_pr(seq, len, (rnti<<14) + ((nslot/2)<<9) + cell_id); } @@ -82,6 +76,5 @@ int srslte_sequence_pusch(srslte_sequence_t *seq, uint16_t rnti, uint32_t nslot, * 36.211 5.4.2 */ int srslte_sequence_pucch(srslte_sequence_t *seq, uint16_t rnti, uint32_t nslot, uint32_t cell_id) { - bzero(seq, sizeof(srslte_sequence_t)); return srslte_sequence_LTE_pr(seq, 20, ((((nslot/2)+1)*(2*cell_id+1))<<16)+rnti); } diff --git a/lib/src/phy/phch/test/pbch_file_test.c b/lib/src/phy/phch/test/pbch_file_test.c index f3e4b9b08..734640d55 100644 --- a/lib/src/phy/phch/test/pbch_file_test.c +++ b/lib/src/phy/phch/test/pbch_file_test.c @@ -131,7 +131,11 @@ int base_init() { return -1; } - if (srslte_chest_dl_init(&chest, cell)) { + if (srslte_chest_dl_init(&chest, cell.nof_prb)) { + fprintf(stderr, "Error initializing equalizer\n"); + return -1; + } + if (srslte_chest_dl_set_cell(&chest, cell)) { fprintf(stderr, "Error initializing equalizer\n"); return -1; } @@ -141,7 +145,11 @@ int base_init() { return -1; } - if (srslte_pbch_init(&pbch, cell)) { + if (srslte_pbch_init(&pbch)) { + fprintf(stderr, "Error initiating PBCH\n"); + return -1; + } + if (srslte_pbch_set_cell(&pbch, cell)) { fprintf(stderr, "Error initiating PBCH\n"); return -1; } diff --git a/lib/src/phy/phch/test/pbch_test.c b/lib/src/phy/phch/test/pbch_test.c index c86e6f48a..a8c673714 100644 --- a/lib/src/phy/phch/test/pbch_test.c +++ b/lib/src/phy/phch/test/pbch_test.c @@ -104,7 +104,11 @@ int main(int argc, char **argv) { } } - if (srslte_pbch_init(&pbch, cell)) { + if (srslte_pbch_init(&pbch)) { + fprintf(stderr, "Error creating PBCH object\n"); + exit(-1); + } + if (srslte_pbch_set_cell(&pbch, cell)) { fprintf(stderr, "Error creating PBCH object\n"); exit(-1); } diff --git a/lib/src/phy/phch/test/pcfich_file_test.c b/lib/src/phy/phch/test/pcfich_file_test.c index 27b50baeb..bd1bc87c2 100644 --- a/lib/src/phy/phch/test/pcfich_file_test.c +++ b/lib/src/phy/phch/test/pcfich_file_test.c @@ -142,7 +142,11 @@ int base_init() { } } - if (srslte_chest_dl_init(&chest, cell)) { + if (srslte_chest_dl_init(&chest, cell.nof_prb)) { + fprintf(stderr, "Error initializing equalizer\n"); + return -1; + } + if (srslte_chest_dl_set_cell(&chest, cell)) { fprintf(stderr, "Error initializing equalizer\n"); return -1; } @@ -157,7 +161,11 @@ int base_init() { return -1; } - if (srslte_pcfich_init(&pcfich, ®s, cell)) { + if (srslte_pcfich_init(&pcfich)) { + fprintf(stderr, "Error creating PBCH object\n"); + return -1; + } + if (srslte_pcfich_set_cell(&pcfich, ®s, cell)) { fprintf(stderr, "Error creating PBCH object\n"); return -1; } diff --git a/lib/src/phy/phch/test/pcfich_test.c b/lib/src/phy/phch/test/pcfich_test.c index 5d90b645a..d9217586f 100644 --- a/lib/src/phy/phch/test/pcfich_test.c +++ b/lib/src/phy/phch/test/pcfich_test.c @@ -124,7 +124,11 @@ int main(int argc, char **argv) { exit(-1); } - if (srslte_pcfich_init(&pcfich, ®s, cell)) { + if (srslte_pcfich_init(&pcfich)) { + fprintf(stderr, "Error creating PBCH object\n"); + exit(-1); + } + if (srslte_pcfich_set_cell(&pcfich, ®s, cell)) { fprintf(stderr, "Error creating PBCH object\n"); exit(-1); } diff --git a/lib/src/phy/phch/test/pdcch_file_test.c b/lib/src/phy/phch/test/pdcch_file_test.c index b505e6b68..4d61e529a 100644 --- a/lib/src/phy/phch/test/pdcch_file_test.c +++ b/lib/src/phy/phch/test/pdcch_file_test.c @@ -148,7 +148,11 @@ int base_init() { } } - if (srslte_chest_dl_init(&chest, cell)) { + if (srslte_chest_dl_init(&chest, cell.nof_prb)) { + fprintf(stderr, "Error initializing equalizer\n"); + return -1; + } + if (srslte_chest_dl_set_cell(&chest, cell)) { fprintf(stderr, "Error initializing equalizer\n"); return -1; } @@ -167,11 +171,15 @@ int base_init() { fprintf(stderr, "Error setting CFI %d\n", cfi); return -1; } - if (srslte_pdcch_init(&pdcch, ®s, cell)) { + if (srslte_pdcch_init(&pdcch, cell.nof_prb)) { fprintf(stderr, "Error creating PDCCH object\n"); exit(-1); } - + if (srslte_pdcch_set_cell(&pdcch, ®s, cell)) { + fprintf(stderr, "Error creating PDCCH object\n"); + exit(-1); + } + DEBUG("Memory init OK\n",0); return 0; } diff --git a/lib/src/phy/phch/test/pdcch_test.c b/lib/src/phy/phch/test/pdcch_test.c index 5d4fb0a7c..6b8ee1731 100644 --- a/lib/src/phy/phch/test/pdcch_test.c +++ b/lib/src/phy/phch/test/pdcch_test.c @@ -177,7 +177,11 @@ int main(int argc, char **argv) { exit(-1); } - if (srslte_pdcch_init(&pdcch, ®s, cell)) { + if (srslte_pdcch_init(&pdcch, cell.nof_prb)) { + fprintf(stderr, "Error creating PDCCH object\n"); + exit(-1); + } + if (srslte_pdcch_set_cell(&pdcch, ®s, cell)) { fprintf(stderr, "Error creating PDCCH object\n"); exit(-1); } diff --git a/lib/src/phy/phch/test/pdsch_pdcch_file_test.c b/lib/src/phy/phch/test/pdsch_pdcch_file_test.c index 0d19d689e..d6bd10018 100644 --- a/lib/src/phy/phch/test/pdsch_pdcch_file_test.c +++ b/lib/src/phy/phch/test/pdsch_pdcch_file_test.c @@ -137,11 +137,15 @@ int base_init() { exit(-1); } - if (srslte_ue_dl_init_multi(&ue_dl, cell, 1)) { + if (srslte_ue_dl_init_multi(&ue_dl, cell.nof_prb, 1)) { fprintf(stderr, "Error initializing UE DL\n"); return -1; } - + if (srslte_ue_dl_set_cell(&ue_dl, cell)) { + fprintf(stderr, "Error initializing UE DL\n"); + return -1; + } + srslte_ue_dl_set_rnti(&ue_dl, rnti); DEBUG("Memory init OK\n",0); diff --git a/lib/src/phy/phch/test/pdsch_test.c b/lib/src/phy/phch/test/pdsch_test.c index d4e5163d3..34150f4db 100644 --- a/lib/src/phy/phch/test/pdsch_test.c +++ b/lib/src/phy/phch/test/pdsch_test.c @@ -177,11 +177,15 @@ int main(int argc, char **argv) { goto quit; } - if (srslte_pdsch_init(&pdsch, cell)) { + if (srslte_pdsch_init_ue(&pdsch, cell.nof_prb)) { fprintf(stderr, "Error creating PDSCH object\n"); goto quit; } - + if (srslte_pdsch_set_cell(&pdsch, cell)) { + fprintf(stderr, "Error creating PDSCH object\n"); + goto quit; + } + srslte_pdsch_set_rnti(&pdsch, rnti); if (srslte_softbuffer_rx_init(&softbuffer_rx, cell.nof_prb)) { @@ -202,11 +206,15 @@ int main(int argc, char **argv) { #endif srslte_chest_dl_t chest; - if (srslte_chest_dl_init(&chest, cell)) { + if (srslte_chest_dl_init(&chest, cell.nof_prb)) { printf("Error initializing equalizer\n"); exit(-1); } - srslte_chest_dl_estimate(&chest, slot_symbols[0], ce, subframe); + if (srslte_chest_dl_set_cell(&chest, cell)) { + printf("Error initializing equalizer\n"); + exit(-1); + } + srslte_chest_dl_estimate(&chest, slot_symbols[0], ce, subframe); srslte_chest_dl_free(&chest); srslte_filesource_free(&fsrc); diff --git a/lib/src/phy/phch/test/phich_file_test.c b/lib/src/phy/phch/test/phich_file_test.c index f037a55da..27e9bc14e 100644 --- a/lib/src/phy/phch/test/phich_file_test.c +++ b/lib/src/phy/phch/test/phich_file_test.c @@ -29,6 +29,7 @@ #include #include #include +#include #include "srslte/srslte.h" @@ -165,7 +166,11 @@ int base_init() { } } - if (srslte_chest_dl_init(&chest, cell)) { + if (srslte_chest_dl_init(&chest, cell.nof_prb)) { + fprintf(stderr, "Error initializing equalizer\n"); + return -1; + } + if (srslte_chest_dl_set_cell(&chest, cell)) { fprintf(stderr, "Error initializing equalizer\n"); return -1; } @@ -180,7 +185,11 @@ int base_init() { return -1; } - if (srslte_phich_init(&phich, ®s, cell)) { + if (srslte_phich_init(&phich)) { + fprintf(stderr, "Error creating PBCH object\n"); + return -1; + } + if (srslte_phich_set_cell(&phich, ®s, cell)) { fprintf(stderr, "Error creating PBCH object\n"); return -1; } diff --git a/lib/src/phy/phch/test/phich_test.c b/lib/src/phy/phch/test/phich_test.c index d1c6ef964..1269e02bd 100644 --- a/lib/src/phy/phch/test/phich_test.c +++ b/lib/src/phy/phch/test/phich_test.c @@ -142,6 +142,10 @@ int main(int argc, char **argv) { cid = cell.id; max_cid = cell.id; } + if (srslte_phich_init(&phich)) { + fprintf(stderr, "Error creating PBCH object\n"); + exit(-1); + } while(cid <= max_cid) { cell.id = cid; @@ -152,7 +156,7 @@ int main(int argc, char **argv) { exit(-1); } - if (srslte_phich_init(&phich, ®s, cell)) { + if (srslte_phich_set_cell(&phich, ®s, cell)) { fprintf(stderr, "Error creating PBCH object\n"); exit(-1); } @@ -198,10 +202,10 @@ int main(int argc, char **argv) { } } } - srslte_phich_free(&phich); srslte_regs_free(®s); cid++; } + srslte_phich_free(&phich); for (i=0;i 0) { cfg.rv = rv_idx; - if (srslte_pusch_encode(&pusch, &cfg, &softbuffer_tx, data, uci_data_tx, rnti, sf_symbols)) { + if (srslte_pusch_encode(&pusch_tx, &cfg, &softbuffer_tx, data, uci_data_tx, rnti, sf_symbols)) { fprintf(stderr, "Error encoding TB\n"); exit(-1); } @@ -233,7 +251,7 @@ int main(int argc, char **argv) { } gettimeofday(&t[1], NULL); - int r = srslte_pusch_decode(&pusch, &cfg, &softbuffer_rx, sf_symbols, ce, 0, rnti, data, &uci_data_rx); + int r = srslte_pusch_decode(&pusch_rx, &cfg, &softbuffer_rx, sf_symbols, ce, 0, rnti, data, &uci_data_rx); gettimeofday(&t[2], NULL); get_time_interval(t); if (r) { @@ -265,7 +283,8 @@ int main(int argc, char **argv) { } quit: - srslte_pusch_free(&pusch); + srslte_pusch_free(&pusch_tx); + srslte_pusch_free(&pusch_rx); srslte_softbuffer_tx_free(&softbuffer_tx); if (sf_symbols) { diff --git a/lib/src/phy/resampling/interp.c b/lib/src/phy/resampling/interp.c index 553caf4b7..180b3f9fc 100644 --- a/lib/src/phy/resampling/interp.c +++ b/lib/src/phy/resampling/interp.c @@ -27,7 +27,8 @@ #include #include #include -#include +#include +#include #include "srslte/phy/resampling/interp.h" #include "srslte/phy/utils/vector.h" @@ -108,11 +109,23 @@ int srslte_interp_linear_vector_init(srslte_interp_linsrslte_vec_t *q, uint32_t perror("malloc"); return SRSLTE_ERROR; } - q->vector_len = vector_len; + q->vector_len = vector_len; + q->max_vector_len = vector_len; } return ret; } +int srslte_interp_linear_vector_resize(srslte_interp_linsrslte_vec_t *q, uint32_t vector_len) +{ + if (vector_len <= q->max_vector_len) { + q->vector_len = vector_len; + return SRSLTE_SUCCESS; + } else { + fprintf(stderr, "Error resizing interp_linear: vector_len must be lower or equal than initialized\n"); + return SRSLTE_ERROR; + } +} + void srslte_interp_linear_vector_free(srslte_interp_linsrslte_vec_t *q) { if (q->diff_vec) { free(q->diff_vec); @@ -189,7 +202,9 @@ int srslte_interp_linear_init(srslte_interp_lin_t *q, uint32_t vector_len, uint3 } q->vector_len = vector_len; - q->M = M; + q->M = M; + q->max_vector_len = vector_len; + q->max_M = M; } return ret; } @@ -209,6 +224,24 @@ void srslte_interp_linear_free(srslte_interp_lin_t *q) { } + +int srslte_interp_linear_resize(srslte_interp_lin_t *q, uint32_t vector_len, uint32_t M) +{ + if (vector_len <= q->max_vector_len && M <= q->max_M) { + + for (int i=0;iramp[i] = (float) i; + } + + q->vector_len = vector_len; + q->M = M; + return SRSLTE_SUCCESS; + } else { + fprintf(stderr, "Error resizing interp_linear: vector_len and M must be lower or equal than initialized\n"); + return SRSLTE_ERROR; + } +} + void srslte_interp_linear_offset(srslte_interp_lin_t *q, cf_t *input, cf_t *output, uint32_t off_st, uint32_t off_end) { diff --git a/lib/src/phy/rf/rf_utils.c b/lib/src/phy/rf/rf_utils.c index f4a2c6790..ce288b5c5 100644 --- a/lib/src/phy/rf/rf_utils.c +++ b/lib/src/phy/rf/rf_utils.c @@ -103,11 +103,16 @@ int rf_mib_decoder(srslte_rf_t *rf, uint32_t nof_rx_antennas,cell_search_cfg_t * srslte_ue_mib_sync_t ue_mib; uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN]; - if (srslte_ue_mib_sync_init_multi(&ue_mib, cell->id, cell->cp, srslte_rf_recv_wrapper_cs, nof_rx_antennas, (void*) rf)) { + if (srslte_ue_mib_sync_init_multi(&ue_mib, srslte_rf_recv_wrapper_cs, nof_rx_antennas, (void*) rf)) { fprintf(stderr, "Error initiating srslte_ue_mib_sync\n"); goto clean_exit; } - + + if (srslte_ue_mib_sync_set_cell(&ue_mib, cell->id, cell->cp)) { + fprintf(stderr, "Error initiating srslte_ue_mib_sync\n"); + goto clean_exit; + } + if (config->init_agc > 0) { srslte_ue_sync_start_agc(&ue_mib.ue_sync, srslte_rf_set_rx_gain_th_wrapper, config->init_agc); } @@ -168,7 +173,6 @@ int rf_cell_search(srslte_rf_t *rf, uint32_t nof_rx_antennas, fprintf(stderr, "Error initiating UE cell detect\n"); return SRSLTE_ERROR; } - if (config->nof_valid_pss_frames) { srslte_ue_cellsearch_set_nof_valid_frames(&cs, config->nof_valid_pss_frames); } diff --git a/lib/src/phy/scrambling/scrambling.c b/lib/src/phy/scrambling/scrambling.c index bb5637814..42f16d1e8 100644 --- a/lib/src/phy/scrambling/scrambling.c +++ b/lib/src/phy/scrambling/scrambling.c @@ -33,29 +33,29 @@ #include "srslte/phy/scrambling/scrambling.h" void srslte_scrambling_f(srslte_sequence_t *s, float *data) { - srslte_scrambling_f_offset(s, data, 0, s->len); + srslte_scrambling_f_offset(s, data, 0, s->cur_len); } void srslte_scrambling_f_offset(srslte_sequence_t *s, float *data, int offset, int len) { - assert (len + offset <= s->len); + assert (len + offset <= s->cur_len); srslte_vec_prod_fff(data, &s->c_float[offset], data, len); } void srslte_scrambling_s(srslte_sequence_t *s, short *data) { - srslte_scrambling_s_offset(s, data, 0, s->len); + srslte_scrambling_s_offset(s, data, 0, s->cur_len); } void srslte_scrambling_s_offset(srslte_sequence_t *s, short *data, int offset, int len) { - assert (len + offset <= s->len); + assert (len + offset <= s->cur_len); srslte_vec_prod_sss(data, &s->c_short[offset], data, len); } void srslte_scrambling_c(srslte_sequence_t *s, cf_t *data) { - srslte_scrambling_c_offset(s, data, 0, s->len); + srslte_scrambling_c_offset(s, data, 0, s->cur_len); } void srslte_scrambling_c_offset(srslte_sequence_t *s, cf_t *data, int offset, int len) { - assert (len + offset <= s->len); + assert (len + offset <= s->cur_len); srslte_vec_prod_cfc(data, &s->c_float[offset], data, len); } @@ -81,7 +81,7 @@ void scrambling_b_word(uint8_t *c, uint8_t *data, int len) { void srslte_scrambling_b(srslte_sequence_t *s, uint8_t *data) { - scrambling_b_word(s->c, data, s->len); + scrambling_b_word(s->c, data, s->cur_len); } void srslte_scrambling_b_offset(srslte_sequence_t *s, uint8_t *data, int offset, int len) { diff --git a/lib/src/phy/scrambling/test/scrambling_test.c b/lib/src/phy/scrambling/test/scrambling_test.c index 9ff47dc85..40722f09b 100644 --- a/lib/src/phy/scrambling/test/scrambling_test.c +++ b/lib/src/phy/scrambling/test/scrambling_test.c @@ -84,8 +84,10 @@ void parse_args(int argc, char **argv) { int init_sequence(srslte_sequence_t *seq, char *name) { if (!strcmp(name, "PBCH")) { + bzero(seq, sizeof(srslte_sequence_t)); return srslte_sequence_pbch(seq, cp, cell_id); } else if (!strcmp(name, "PDSCH")) { + bzero(seq, sizeof(srslte_sequence_t)); return srslte_sequence_pdsch(seq, 1234, 0, 0, cell_id, nof_bits); } else { fprintf(stderr, "Unsupported sequence name %s\n", name); @@ -109,18 +111,18 @@ int main(int argc, char **argv) { } if (!do_floats) { - input_b = malloc(sizeof(uint8_t) * seq.len); + input_b = malloc(sizeof(uint8_t) * seq.cur_len); if (!input_b) { perror("malloc"); exit(-1); } - scrambled_b = malloc(sizeof(uint8_t) * seq.len); + scrambled_b = malloc(sizeof(uint8_t) * seq.cur_len); if (!scrambled_b) { perror("malloc"); exit(-1); } - for (i=0;i #include #include +#include #include "srslte/phy/utils/cexptab.h" #include "srslte/phy/sync/cfo.h" @@ -47,6 +48,7 @@ int srslte_cfo_init(srslte_cfo_t *h, uint32_t nsamples) { h->tol = SRSLTE_CFO_TOLERANCE; h->last_freq = 0; h->nsamples = nsamples; + h->max_samples = nsamples; srslte_cexptab_gen(&h->tab, h->cur_cexp, h->last_freq, h->nsamples); ret = SRSLTE_SUCCESS; @@ -69,15 +71,15 @@ void srslte_cfo_set_tol(srslte_cfo_t *h, float tol) { h->tol = tol; } -int srslte_cfo_realloc(srslte_cfo_t *h, uint32_t samples) { - h->cur_cexp = realloc(h->cur_cexp, sizeof(cf_t) * samples); - if (!h->cur_cexp) { - perror("realloc"); +int srslte_cfo_resize(srslte_cfo_t *h, uint32_t samples) { + if (samples <= h->max_samples) { + srslte_cexptab_gen(&h->tab, h->cur_cexp, h->last_freq, samples); + h->nsamples = samples; + } else { + fprintf(stderr, "Error in cfo_resize(): nof_samples must be lower than initialized\n"); return SRSLTE_ERROR; } - srslte_cexptab_gen(&h->tab, h->cur_cexp, h->last_freq, samples); - h->nsamples = samples; - + return SRSLTE_SUCCESS; } diff --git a/lib/src/phy/sync/cp.c b/lib/src/phy/sync/cp.c index c745aca85..a282f6dfd 100644 --- a/lib/src/phy/sync/cp.c +++ b/lib/src/phy/sync/cp.c @@ -25,6 +25,7 @@ */ #include +#include #include "srslte/phy/sync/cp.h" #include "srslte/phy/utils/vector.h" @@ -33,7 +34,8 @@ int srslte_cp_synch_init(srslte_cp_synch_t *q, uint32_t symbol_sz) { q->symbol_sz = symbol_sz; - + q->max_symbol_sz = symbol_sz; + q->corr = srslte_vec_malloc(sizeof(cf_t) * q->symbol_sz); if (!q->corr) { perror("malloc"); @@ -49,6 +51,18 @@ void srslte_cp_synch_free(srslte_cp_synch_t *q) } } +int srslte_cp_synch_resize(srslte_cp_synch_t *q, uint32_t symbol_sz) +{ + if (symbol_sz > q->max_symbol_sz) { + fprintf(stderr, "Error in cp_synch_resize(): symbol_sz must be lower than initialized\n"); + return SRSLTE_ERROR; + } + q->symbol_sz = symbol_sz; + + return SRSLTE_SUCCESS; +} + + uint32_t srslte_cp_synch(srslte_cp_synch_t *q, cf_t *input, uint32_t max_offset, uint32_t nof_symbols, uint32_t cp_len) { if (max_offset > q->symbol_sz) { diff --git a/lib/src/phy/sync/pss.c b/lib/src/phy/sync/pss.c index 2ad166bc0..3d221528c 100644 --- a/lib/src/phy/sync/pss.c +++ b/lib/src/phy/sync/pss.c @@ -93,7 +93,9 @@ int srslte_pss_synch_init_fft_offset(srslte_pss_synch_t *q, uint32_t frame_size, * It correlates a signal of frame_size samples with the PSS sequence in the frequency * domain. The PSS sequence is transformed using fft_size samples. */ -int srslte_pss_synch_init_fft_offset_decim(srslte_pss_synch_t *q, uint32_t frame_size, uint32_t fft_size, int offset, int decimate) { +int srslte_pss_synch_init_fft_offset_decim(srslte_pss_synch_t *q, + uint32_t max_frame_size, uint32_t max_fft_size, + int offset, int decimate) { int ret = SRSLTE_ERROR_INVALID_INPUTS; @@ -107,18 +109,20 @@ int srslte_pss_synch_init_fft_offset_decim(srslte_pss_synch_t *q, uint32_t frame q->N_id_2 = 10; q->ema_alpha = 0.2; - + + q->max_fft_size = max_fft_size; + q->max_frame_size = max_frame_size; + q->decimate = decimate; - fft_size = fft_size/q->decimate; - frame_size = frame_size/q->decimate; + uint32_t fft_size = max_fft_size/q->decimate; + uint32_t frame_size = max_frame_size/q->decimate; q->fft_size = fft_size; q->frame_size = frame_size; buffer_size = fft_size + frame_size + 1; - if(q->decimate > 1) - { + if(q->decimate > 1) { int filter_order = 3; srslte_filt_decim_cc_init(&q->filter,q->decimate,filter_order); q->filter.filter_output = srslte_vec_malloc((buffer_size) * sizeof(cf_t)); @@ -175,7 +179,6 @@ int srslte_pss_synch_init_fft_offset_decim(srslte_pss_synch_t *q, uint32_t frame goto clean_and_exit; } bzero(&q->pss_signal_time[N_id_2][q->fft_size], q->frame_size * sizeof(cf_t)); - } #ifdef CONVOLUTION_FFT @@ -208,6 +211,79 @@ clean_and_exit: } +/* Initializes the PSS synchronization object. + * + * It correlates a signal of frame_size samples with the PSS sequence in the frequency + * domain. The PSS sequence is transformed using fft_size samples. + */ +int srslte_pss_synch_resize(srslte_pss_synch_t *q, uint32_t frame_size, uint32_t fft_size, int offset) { + + + int ret = SRSLTE_ERROR_INVALID_INPUTS; + if (q != NULL) { + + ret = SRSLTE_ERROR; + + if (fft_size > q->max_fft_size || frame_size > q->max_frame_size) { + fprintf(stderr, "Error in pss_synch_config(): fft_size and frame_size must be lower than initialized\n"); + return SRSLTE_ERROR; + } + + uint32_t N_id_2; + uint32_t buffer_size; + + q->N_id_2 = 10; + q->ema_alpha = 0.2; + + fft_size = fft_size/q->decimate; + frame_size = frame_size/q->decimate; + + q->fft_size = fft_size; + q->frame_size = frame_size; + + buffer_size = fft_size + frame_size + 1; + + if (srslte_dft_replan(&q->dftp_input, fft_size)) { + fprintf(stderr, "Error creating DFT plan \n"); + return SRSLTE_ERROR; + } + + bzero(&q->tmp_input[q->frame_size], q->fft_size * sizeof(cf_t)); + bzero(q->conv_output, sizeof(cf_t) * buffer_size); + bzero(q->conv_output_avg, sizeof(float) * buffer_size); + +#ifdef SRSLTE_PSS_ACCUMULATE_ABS + bzero(q->conv_output_abs, sizeof(float) * buffer_size); +#endif + + // Generate PSS sequences for this FFT size + for (N_id_2=0;N_id_2<3;N_id_2++) { + if (srslte_pss_synch_init_N_id_2(q->pss_signal_freq[N_id_2], q->pss_signal_time[N_id_2], N_id_2, fft_size, offset)) { + fprintf(stderr, "Error initiating PSS detector for N_id_2=%d fft_size=%d\n", N_id_2, fft_size); + return SRSLTE_ERROR; + } + bzero(&q->pss_signal_time[N_id_2][q->fft_size], q->frame_size * sizeof(cf_t)); + } +#ifdef CONVOLUTION_FFT + + if (srslte_conv_fft_cc_replan(&q->conv_fft, frame_size, fft_size)) { + fprintf(stderr, "Error initiating convolution FFT\n"); + return SRSLTE_ERROR; + } + for(int i =0; i< 3; i++) { + srslte_dft_run_c(&q->conv_fft.filter_plan, q->pss_signal_time[i], q->pss_signal_freq_full[i]); + } + +#endif + + srslte_pss_synch_reset(q); + + ret = SRSLTE_SUCCESS; + } + return ret; + +} + void srslte_pss_synch_free(srslte_pss_synch_t *q) { uint32_t i; diff --git a/lib/src/phy/sync/sss.c b/lib/src/phy/sync/sss.c index 3586e04de..4ed7b1d6c 100644 --- a/lib/src/phy/sync/sss.c +++ b/lib/src/phy/sync/sss.c @@ -58,7 +58,8 @@ int srslte_sss_synch_init(srslte_sss_synch_t *q, uint32_t fft_size) { srslte_dft_plan_set_dc(&q->dftp_input, true); q->fft_size = fft_size; - + q->max_fft_size = fft_size; + generate_N_id_1_table(q->N_id_1_table); for (N_id_2=0;N_id_2<3;N_id_2++) { @@ -71,19 +72,18 @@ int srslte_sss_synch_init(srslte_sss_synch_t *q, uint32_t fft_size) { return SRSLTE_ERROR_INVALID_INPUTS; } -int srslte_sss_synch_realloc(srslte_sss_synch_t *q, uint32_t fft_size) { +int srslte_sss_synch_resize(srslte_sss_synch_t *q, uint32_t fft_size) { if (q != NULL && fft_size <= 2048) { - srslte_dft_plan_free(&q->dftp_input); - if (srslte_dft_plan(&q->dftp_input, fft_size, SRSLTE_DFT_FORWARD, SRSLTE_DFT_COMPLEX)) { + if (fft_size > q->max_fft_size) { + fprintf(stderr, "Error in sss_synch_resize(): fft_size must be lower than initialized\n"); + return SRSLTE_ERROR; + } + if (srslte_dft_replan(&q->dftp_input, fft_size)) { srslte_sss_synch_free(q); return SRSLTE_ERROR; } - srslte_dft_plan_set_mirror(&q->dftp_input, true); - srslte_dft_plan_set_norm(&q->dftp_input, true); - srslte_dft_plan_set_dc(&q->dftp_input, true); - q->fft_size = fft_size; return SRSLTE_SUCCESS; } diff --git a/lib/src/phy/sync/sync.c b/lib/src/phy/sync/sync.c index fb77e1b25..99d58a46f 100644 --- a/lib/src/phy/sync/sync.c +++ b/lib/src/phy/sync/sync.c @@ -28,6 +28,7 @@ #include #include #include +#include #include "srslte/phy/utils/debug.h" #include "srslte/phy/common/phy_common.h" @@ -36,7 +37,7 @@ #include "srslte/phy/sync/cfo.h" #define MEANPEAK_EMA_ALPHA 0.1 -#define CFO_EMA_ALPHA 0.1 +#define CFO_EMA_ALPHA 0.2 #define CP_EMA_ALPHA 0.1 static bool fft_size_isvalid(uint32_t fft_size) { @@ -77,7 +78,8 @@ int srslte_sync_init_decim(srslte_sync_t *q, uint32_t frame_size, uint32_t max_o q->frame_size = frame_size; q->max_offset = max_offset; q->sss_alg = SSS_FULL; - + q->max_frame_size = frame_size; + q->enable_cfo_corr = true; if (srslte_cfo_init(&q->cfocorr, q->frame_size)) { fprintf(stderr, "Error initiating CFO\n"); @@ -91,8 +93,6 @@ int srslte_sync_init_decim(srslte_sync_t *q, uint32_t frame_size, uint32_t max_o // Set a CFO tolerance of approx 50 Hz srslte_cfo_set_tol(&q->cfocorr, 50.0/(15000.0*q->fft_size)); - - // Set a CFO tolerance of approx 50 Hz srslte_cfo_set_tol(&q->cfocorr2, 50.0/(15000.0*q->fft_size)); for (int i=0;i<2;i++) { @@ -113,8 +113,7 @@ int srslte_sync_init_decim(srslte_sync_t *q, uint32_t frame_size, uint32_t max_o q->decimate = decimate; if(!decimate) decimate = 1; - - + if (srslte_pss_synch_init_fft_offset_decim(&q->pss, max_offset, fft_size,0,decimate)) { fprintf(stderr, "Error initializing PSS object\n"); goto clean_exit; @@ -162,6 +161,77 @@ void srslte_sync_free(srslte_sync_t *q) { } } +int srslte_sync_resize(srslte_sync_t *q, uint32_t frame_size, uint32_t max_offset, uint32_t fft_size) { + + int ret = SRSLTE_ERROR_INVALID_INPUTS; + + if (q != NULL && + frame_size <= 307200 && + fft_size_isvalid(fft_size)) + { + ret = SRSLTE_ERROR; + + if (frame_size > q->max_frame_size) { + fprintf(stderr, "Error in sync_resize(): frame_size must be lower than initialized\n"); + return SRSLTE_ERROR; + } + q->detect_cp = true; + q->sss_en = true; + q->mean_cfo = 0; + q->mean_cfo2 = 0; + q->N_id_2 = 1000; + q->N_id_1 = 1000; + q->cfo_i = 0; + q->find_cfo_i = false; + q->find_cfo_i_initiated = false; + q->cfo_ema_alpha = CFO_EMA_ALPHA; + q->fft_size = fft_size; + q->frame_size = frame_size; + q->max_offset = max_offset; + q->sss_alg = SSS_FULL; + + q->enable_cfo_corr = true; + + if (srslte_pss_synch_resize(&q->pss, max_offset, fft_size, 0)) { + fprintf(stderr, "Error resizing PSS object\n"); + return SRSLTE_ERROR; + } + if (srslte_sss_synch_resize(&q->sss, fft_size)) { + fprintf(stderr, "Error resizing SSS object\n"); + return SRSLTE_ERROR; + } + + if (srslte_cp_synch_resize(&q->cp_synch, fft_size)) { + fprintf(stderr, "Error resizing CFO\n"); + return SRSLTE_ERROR; + } + + if (srslte_cfo_resize(&q->cfocorr, q->frame_size)) { + fprintf(stderr, "Error resizing CFO\n"); + return SRSLTE_ERROR; + } + + if (srslte_cfo_resize(&q->cfocorr2, q->frame_size)) { + fprintf(stderr, "Error resizing CFO\n"); + return SRSLTE_ERROR; + } + + // Update CFO tolerance + srslte_cfo_set_tol(&q->cfocorr, 50.0/(15000.0*q->fft_size)); + srslte_cfo_set_tol(&q->cfocorr2, 50.0/(15000.0*q->fft_size)); + + + DEBUG("SYNC init with frame_size=%d, max_offset=%d and fft_size=%d\n", frame_size, max_offset, fft_size); + + ret = SRSLTE_SUCCESS; + } else { + fprintf(stderr, "Invalid parameters frame_size: %d, fft_size: %d\n", frame_size, fft_size); + } + + return ret; +} + + void srslte_sync_set_threshold(srslte_sync_t *q, float threshold) { q->threshold = threshold; } @@ -451,7 +521,7 @@ srslte_sync_find_ret_t srslte_sync_find(srslte_sync_t *q, cf_t *input, uint32_t q->mean_cfo = SRSLTE_VEC_EMA(cfo, q->mean_cfo, q->cfo_ema_alpha); /* Correct CFO with the averaged CFO estimation */ - srslte_cfo_correct(&q->cfocorr2, input, q->temp, -q->mean_cfo / q->fft_size); + srslte_cfo_correct(&q->cfocorr2, input, q->temp, -q->mean_cfo / q->fft_size); input_cfo = q->temp; } diff --git a/lib/src/phy/ue/ue_cell_search.c b/lib/src/phy/ue/ue_cell_search.c index f8c38a1bb..0e92e6dc1 100644 --- a/lib/src/phy/ue/ue_cell_search.c +++ b/lib/src/phy/ue/ue_cell_search.c @@ -29,6 +29,7 @@ #include #include #include +#include #include "srslte/phy/ue/ue_cell_search.h" @@ -51,11 +52,16 @@ int srslte_ue_cellsearch_init(srslte_ue_cellsearch_t * q, uint32_t max_frames, cell.id = SRSLTE_CELL_ID_UNKNOWN; cell.nof_prb = SRSLTE_CS_NOF_PRB; - if (srslte_ue_sync_init(&q->ue_sync, cell, recv_callback, stream_handler)) { + if (srslte_ue_sync_init(&q->ue_sync, cell.nof_prb, true, recv_callback, stream_handler)) { fprintf(stderr, "Error initiating ue_sync\n"); goto clean_exit; } - + + if (srslte_ue_sync_set_cell(&q->ue_sync, cell)) { + fprintf(stderr, "Error initiating ue_sync\n"); + goto clean_exit; + } + q->sf_buffer[0] = srslte_vec_malloc(3*sizeof(cf_t)*SRSLTE_SF_LEN_PRB(100)); q->nof_rx_antennas = 1; @@ -105,11 +111,15 @@ int srslte_ue_cellsearch_init_multi(srslte_ue_cellsearch_t * q, uint32_t max_fra cell.id = SRSLTE_CELL_ID_UNKNOWN; cell.nof_prb = SRSLTE_CS_NOF_PRB; - if (srslte_ue_sync_init_multi(&q->ue_sync, cell, recv_callback, nof_rx_antennas, stream_handler)) { + if (srslte_ue_sync_init_multi(&q->ue_sync, cell.nof_prb, true, recv_callback, nof_rx_antennas, stream_handler)) { fprintf(stderr, "Error initiating ue_sync\n"); goto clean_exit; } - + if (srslte_ue_sync_set_cell(&q->ue_sync, cell)) { + fprintf(stderr, "Error initiating ue_sync\n"); + goto clean_exit; + } + for (int i=0;isf_buffer[i] = srslte_vec_malloc(3*sizeof(cf_t)*SRSLTE_SF_LEN_PRB(100)); } @@ -242,7 +252,8 @@ int srslte_ue_cellsearch_scan(srslte_ue_cellsearch_t * q, { int ret = 0; float max_peak_value = -1.0; - uint32_t nof_detected_cells = 0; + uint32_t nof_detected_cells = 0; + for (uint32_t N_id_2=0;N_id_2<3 && ret >= 0;N_id_2++) { ret = srslte_ue_cellsearch_scan_N_id_2(q, N_id_2, &found_cells[N_id_2]); if (ret < 0) { @@ -273,8 +284,12 @@ int srslte_ue_cellsearch_scan_N_id_2(srslte_ue_cellsearch_t * q, if (q != NULL) { - ret = SRSLTE_SUCCESS; - + ret = SRSLTE_SUCCESS; + + bzero(q->candidates, sizeof(srslte_ue_cellsearch_result_t)*q->max_frames); + bzero(q->mode_ntimes, sizeof(uint32_t)*q->max_frames); + bzero(q->mode_counted, sizeof(uint8_t)*q->max_frames); + srslte_ue_sync_set_N_id_2(&q->ue_sync, N_id_2); srslte_ue_sync_reset(&q->ue_sync); do { diff --git a/lib/src/phy/ue/ue_dl.c b/lib/src/phy/ue/ue_dl.c index 7201f96c2..ab3fa526e 100644 --- a/lib/src/phy/ue/ue_dl.c +++ b/lib/src/phy/ue/ue_dl.c @@ -37,6 +37,7 @@ #define CURRENT_SLOTLEN_RE SRSLTE_SLOT_LEN_RE(q->cell.nof_prb, q->cell.cp) #define CURRENT_SFLEN_RE SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp) +#define MAX_SFLEN_RE SRSLTE_SF_LEN_RE(max_prb, q->cell.cp) static srslte_dci_format_t ue_formats[] = {SRSLTE_DCI_FORMAT1A, SRSLTE_DCI_FORMAT1}; // Only TM1 and TM2 are currently supported const uint32_t nof_ue_formats = 2; @@ -45,80 +46,74 @@ static srslte_dci_format_t common_formats[] = {SRSLTE_DCI_FORMAT1A,SRSLTE_DCI_FO const uint32_t nof_common_formats = 2; int srslte_ue_dl_init(srslte_ue_dl_t *q, - srslte_cell_t cell) + uint32_t max_prb) { - return srslte_ue_dl_init_multi(q, cell, 1); + return srslte_ue_dl_init_multi(q, max_prb, 1); } int srslte_ue_dl_init_multi(srslte_ue_dl_t *q, - srslte_cell_t cell, + uint32_t max_prb, uint32_t nof_rx_antennas) { int ret = SRSLTE_ERROR_INVALID_INPUTS; if (q != NULL && - nof_rx_antennas <= SRSLTE_MAX_PORTS && - srslte_cell_isvalid(&cell)) + nof_rx_antennas <= SRSLTE_MAX_PORTS) { ret = SRSLTE_ERROR; bzero(q, sizeof(srslte_ue_dl_t)); - q->cell = cell; q->pkt_errors = 0; q->pkts_total = 0; q->pending_ul_dci_rnti = 0; q->sample_offset = 0; - q->nof_rx_antennas = nof_rx_antennas; - - if (srslte_ofdm_rx_init(&q->fft, q->cell.cp, q->cell.nof_prb)) { + q->nof_rx_antennas = nof_rx_antennas; + + if (srslte_ofdm_rx_init(&q->fft, SRSLTE_CP_NORM, max_prb)) { fprintf(stderr, "Error initiating FFT\n"); goto clean_exit; } - if (srslte_chest_dl_init(&q->chest, cell)) { + if (srslte_chest_dl_init(&q->chest, max_prb)) { fprintf(stderr, "Error initiating channel estimator\n"); goto clean_exit; } - if (srslte_regs_init(&q->regs, q->cell)) { - fprintf(stderr, "Error initiating REGs\n"); - goto clean_exit; - } - if (srslte_pcfich_init_multi(&q->pcfich, &q->regs, q->cell, nof_rx_antennas)) { + if (srslte_pcfich_init_multi(&q->pcfich, nof_rx_antennas)) { fprintf(stderr, "Error creating PCFICH object\n"); goto clean_exit; } - if (srslte_phich_init(&q->phich, &q->regs, q->cell)) { + if (srslte_phich_init(&q->phich)) { fprintf(stderr, "Error creating PHICH object\n"); goto clean_exit; } - if (srslte_pdcch_init_multi(&q->pdcch, &q->regs, q->cell, nof_rx_antennas)) { + if (srslte_pdcch_init_multi(&q->pdcch, max_prb, nof_rx_antennas)) { fprintf(stderr, "Error creating PDCCH object\n"); goto clean_exit; } - if (srslte_pdsch_init_multi(&q->pdsch, q->cell, nof_rx_antennas)) { + if (srslte_pdsch_init_multi_ue(&q->pdsch, max_prb, nof_rx_antennas)) { fprintf(stderr, "Error creating PDSCH object\n"); goto clean_exit; } - if (srslte_softbuffer_rx_init(&q->softbuffer, q->cell.nof_prb)) { + if (srslte_softbuffer_rx_init(&q->softbuffer, max_prb)) { fprintf(stderr, "Error initiating soft buffer\n"); goto clean_exit; } - if (srslte_cfo_init(&q->sfo_correct, q->cell.nof_prb*SRSLTE_NRE)) { + if (srslte_cfo_init(&q->sfo_correct, max_prb*SRSLTE_NRE)) { fprintf(stderr, "Error initiating SFO correct\n"); goto clean_exit; } srslte_cfo_set_tol(&q->sfo_correct, 1e-5/q->fft.symbol_sz); for (int j=0;jsf_symbols_m[j] = srslte_vec_malloc(CURRENT_SFLEN_RE * sizeof(cf_t)); + q->sf_symbols_m[j] = srslte_vec_malloc(MAX_SFLEN_RE * sizeof(cf_t)); if (!q->sf_symbols_m[j]) { perror("malloc"); goto clean_exit; } - for (uint32_t i=0;icell.nof_ports;i++) { - q->ce_m[i][j] = srslte_vec_malloc(CURRENT_SFLEN_RE * sizeof(cf_t)); + for (uint32_t i=0;ice_m[i][j] = srslte_vec_malloc(MAX_SFLEN_RE * sizeof(cf_t)); if (!q->ce_m[i][j]) { perror("malloc"); goto clean_exit; @@ -127,14 +122,13 @@ int srslte_ue_dl_init_multi(srslte_ue_dl_t *q, } q->sf_symbols = q->sf_symbols_m[0]; - for (int i=0;icell.nof_ports;i++) { + for (int i=0;ice[i] = q->ce_m[i][0]; } ret = SRSLTE_SUCCESS; } else { - fprintf(stderr, "Invalid cell properties: Id=%d, Ports=%d, PRBs=%d\n", - cell.id, cell.nof_ports, cell.nof_prb); + fprintf(stderr, "Invalid parametres\n"); } clean_exit: @@ -159,7 +153,7 @@ void srslte_ue_dl_free(srslte_ue_dl_t *q) { if (q->sf_symbols_m[j]) { free(q->sf_symbols_m[j]); } - for (uint32_t i=0;icell.nof_ports;i++) { + for (uint32_t i=0;ice_m[i][j]) { free(q->ce_m[i][j]); } @@ -169,6 +163,67 @@ void srslte_ue_dl_free(srslte_ue_dl_t *q) { } } +int srslte_ue_dl_set_cell(srslte_ue_dl_t *q, srslte_cell_t cell) +{ + int ret = SRSLTE_ERROR_INVALID_INPUTS; + + if (q != NULL && + srslte_cell_isvalid(&cell)) + { + q->pkt_errors = 0; + q->pkts_total = 0; + q->pending_ul_dci_rnti = 0; + q->sample_offset = 0; + + if (q->cell.id != cell.id || q->cell.nof_prb == 0) { + if (q->cell.nof_prb != 0) { + srslte_regs_free(&q->regs); + } + memcpy(&q->cell, &cell, sizeof(srslte_cell_t)); + if (srslte_regs_init(&q->regs, q->cell)) { + fprintf(stderr, "Error resizing REGs\n"); + return SRSLTE_ERROR; + } + if (srslte_cfo_resize(&q->sfo_correct, q->cell.nof_prb*SRSLTE_NRE)) { + fprintf(stderr, "Error resizing SFO correct\n"); + return SRSLTE_ERROR; + } + srslte_cfo_set_tol(&q->sfo_correct, 1e-5/q->fft.symbol_sz); + if (srslte_ofdm_rx_set_prb(&q->fft, q->cell.cp, q->cell.nof_prb)) { + fprintf(stderr, "Error resizing FFT\n"); + return SRSLTE_ERROR; + } + if (srslte_chest_dl_set_cell(&q->chest, q->cell)) { + fprintf(stderr, "Error resizing channel estimator\n"); + return SRSLTE_ERROR; + } + if (srslte_pcfich_set_cell(&q->pcfich, &q->regs, q->cell)) { + fprintf(stderr, "Error resizing PCFICH object\n"); + return SRSLTE_ERROR; + } + if (srslte_phich_set_cell(&q->phich, &q->regs, q->cell)) { + fprintf(stderr, "Error resizing PHICH object\n"); + return SRSLTE_ERROR; + } + + if (srslte_pdcch_set_cell(&q->pdcch, &q->regs, q->cell)) { + fprintf(stderr, "Error resizing PDCCH object\n"); + return SRSLTE_ERROR; + } + + if (srslte_pdsch_set_cell(&q->pdsch, q->cell)) { + fprintf(stderr, "Error creating PDSCH object\n"); + return SRSLTE_ERROR; + } + } + ret = SRSLTE_SUCCESS; + } else { + fprintf(stderr, "Invalid cell properties: Id=%d, Ports=%d, PRBs=%d\n", + cell.id, cell.nof_ports, cell.nof_prb); + } + return ret; +} + /* Precalculate the PDSCH scramble sequences for a given RNTI. This function takes a while * to execute, so shall be called once the final C-RNTI has been allocated for the session. * For the connection procedure, use srslte_pusch_encode_rnti() or srslte_pusch_decode_rnti() functions @@ -231,7 +286,7 @@ int srslte_ue_dl_decode_fft_estimate_multi(srslte_ue_dl_t *q, cf_t *input[SRSLTE /* Correct SFO multiplying by complex exponential in the time domain */ if (q->sample_offset) { for (int i=0;i<2*SRSLTE_CP_NSYMB(q->cell.cp);i++) { - srslte_cfo_correct(&q->sfo_correct, + srslte_cfo_correct(&q->sfo_correct, &q->sf_symbols_m[j][i*q->cell.nof_prb*SRSLTE_NRE], &q->sf_symbols_m[j][i*q->cell.nof_prb*SRSLTE_NRE], q->sample_offset / q->fft.symbol_sz); @@ -566,11 +621,11 @@ bool srslte_ue_dl_decode_phich(srslte_ue_dl_t *q, uint32_t sf_idx, uint32_t n_pr } void srslte_ue_dl_save_signal(srslte_ue_dl_t *q, srslte_softbuffer_rx_t *softbuffer, uint32_t tti, uint32_t rv_idx, uint16_t rnti, uint32_t cfi) { - srslte_vec_save_file("sf_symbols", q->sf_symbols_m, SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)*sizeof(cf_t)); + srslte_vec_save_file("sf_symbols", q->sf_symbols, SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)*sizeof(cf_t)); printf("%d samples\n", SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)); - srslte_vec_save_file("ce0", q->ce_m[0], SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)*sizeof(cf_t)); + srslte_vec_save_file("ce0", q->ce[0], SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)*sizeof(cf_t)); if (q->cell.nof_ports > 1) { - srslte_vec_save_file("ce1", q->ce_m[1], SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)*sizeof(cf_t)); + srslte_vec_save_file("ce1", q->ce[1], SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)*sizeof(cf_t)); } srslte_vec_save_file("pcfich_ce0", q->pcfich.ce[0], q->pcfich.nof_symbols*sizeof(cf_t)); srslte_vec_save_file("pcfich_ce1", q->pcfich.ce[1], q->pcfich.nof_symbols*sizeof(cf_t)); @@ -583,10 +638,11 @@ void srslte_ue_dl_save_signal(srslte_ue_dl_t *q, srslte_softbuffer_rx_t *softbuf srslte_vec_save_file("pdcch_symbols", q->pdcch.symbols[0], q->pdcch.nof_cce*36*sizeof(cf_t)); srslte_vec_save_file("pdcch_eq_symbols", q->pdcch.d, q->pdcch.nof_cce*36*sizeof(cf_t)); srslte_vec_save_file("pdcch_llr", q->pdcch.llr, q->pdcch.nof_cce*72*sizeof(float)); - - - srslte_vec_save_file("pdsch_symbols", q->pdsch.d, q->pdsch_cfg.nbits.nof_re*sizeof(cf_t)); - srslte_vec_save_file("llr", q->pdsch.e, q->pdsch_cfg.nbits.nof_bits*sizeof(cf_t)); + + + srslte_vec_save_file("pdsch_symbols", q->pdsch.symbols[0], q->pdsch_cfg.nbits.nof_re*sizeof(cf_t)); + srslte_vec_save_file("pdsch_eq_symbols", q->pdsch.d, q->pdsch_cfg.nbits.nof_re*sizeof(cf_t)); + srslte_vec_save_file("pdsch_llr", q->pdsch.e, q->pdsch_cfg.nbits.nof_bits*sizeof(cf_t)); int cb_len = q->pdsch_cfg.cb_segm.K1; for (int i=0;ipdsch_cfg.cb_segm.C;i++) { char tmpstr[64]; diff --git a/lib/src/phy/ue/ue_mib.c b/lib/src/phy/ue/ue_mib.c index 34c2bc2e3..7f68b9f23 100644 --- a/lib/src/phy/ue/ue_mib.c +++ b/lib/src/phy/ue/ue_mib.c @@ -36,45 +36,40 @@ #include "srslte/phy/utils/vector.h" int srslte_ue_mib_init(srslte_ue_mib_t * q, - srslte_cell_t cell) + uint32_t max_prb) { int ret = SRSLTE_ERROR_INVALID_INPUTS; - if (q != NULL && - cell.nof_ports <= SRSLTE_MAX_PORTS) + if (q != NULL) { ret = SRSLTE_ERROR; bzero(q, sizeof(srslte_ue_mib_t)); - if (srslte_pbch_init(&q->pbch, cell)) { + if (srslte_pbch_init(&q->pbch)) { fprintf(stderr, "Error initiating PBCH\n"); goto clean_exit; } - if (cell.nof_ports == 0) { - cell.nof_ports = SRSLTE_MAX_PORTS; - } - - q->sf_symbols = srslte_vec_malloc(SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp) * sizeof(cf_t)); + q->sf_symbols = srslte_vec_malloc(SRSLTE_SF_LEN_RE(max_prb, SRSLTE_CP_NORM) * sizeof(cf_t)); if (!q->sf_symbols) { perror("malloc"); goto clean_exit; } - for (int i=0;ice[i] = srslte_vec_malloc(SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp) * sizeof(cf_t)); + for (int i=0;ice[i] = srslte_vec_malloc(SRSLTE_SF_LEN_RE(max_prb, SRSLTE_CP_NORM) * sizeof(cf_t)); if (!q->ce[i]) { perror("malloc"); goto clean_exit; } } - if (srslte_ofdm_rx_init(&q->fft, cell.cp, cell.nof_prb)) { + if (srslte_ofdm_rx_init(&q->fft, SRSLTE_CP_NORM, max_prb)) { fprintf(stderr, "Error initializing FFT\n"); goto clean_exit; } - if (srslte_chest_dl_init(&q->chest, cell)) { + if (srslte_chest_dl_init(&q->chest, max_prb)) { fprintf(stderr, "Error initializing reference signal\n"); goto clean_exit; } @@ -109,6 +104,38 @@ void srslte_ue_mib_free(srslte_ue_mib_t * q) } +int srslte_ue_mib_set_cell(srslte_ue_mib_t * q, + srslte_cell_t cell) +{ + int ret = SRSLTE_ERROR_INVALID_INPUTS; + + if (q != NULL && + cell.nof_ports <= SRSLTE_MAX_PORTS) + { + if (srslte_pbch_set_cell(&q->pbch, cell)) { + fprintf(stderr, "Error initiating PBCH\n"); + return SRSLTE_ERROR; + } + if (srslte_ofdm_rx_set_prb(&q->fft, cell.cp, cell.nof_prb)) { + fprintf(stderr, "Error initializing FFT\n"); + return SRSLTE_ERROR; + } + + if (cell.nof_ports == 0) { + cell.nof_ports = SRSLTE_MAX_PORTS; + } + + if (srslte_chest_dl_set_cell(&q->chest, cell)) { + fprintf(stderr, "Error initializing reference signal\n"); + return SRSLTE_ERROR; + } + srslte_ue_mib_reset(q); + + ret = SRSLTE_SUCCESS; + } + return ret; +} + void srslte_ue_mib_reset(srslte_ue_mib_t * q) { @@ -122,6 +149,8 @@ int srslte_ue_mib_decode(srslte_ue_mib_t * q, cf_t *input, int ret = SRSLTE_SUCCESS; cf_t *ce_slot1[SRSLTE_MAX_PORTS]; + + /* Run FFT for the slot symbols */ srslte_ofdm_rx_sf(&q->fft, input, q->sf_symbols); @@ -142,7 +171,7 @@ int srslte_ue_mib_decode(srslte_ue_mib_t * q, cf_t *input, /* Decode PBCH */ ret = srslte_pbch_decode(&q->pbch, &q->sf_symbols[SRSLTE_SLOT_LEN_RE(q->chest.cell.nof_prb, q->chest.cell.cp)], - ce_slot1, srslte_chest_dl_get_noise_estimate(&q->chest), + ce_slot1, 0, bch_payload, nof_tx_ports, sfn_offset); @@ -161,27 +190,21 @@ int srslte_ue_mib_decode(srslte_ue_mib_t * q, cf_t *input, return ret; } -int srslte_ue_mib_sync_init(srslte_ue_mib_sync_t *q, - uint32_t cell_id, - srslte_cp_t cp, - int (recv_callback)(void*, void*, uint32_t, srslte_timestamp_t*), - void *stream_handler) +int srslte_ue_mib_sync_init_multi(srslte_ue_mib_sync_t *q, + int (recv_callback)(void*, cf_t*[SRSLTE_MAX_PORTS], uint32_t, srslte_timestamp_t*), + uint32_t nof_rx_antennas, + void *stream_handler) { - srslte_cell_t cell; - // If the ports are set to 0, ue_mib goes through 1, 2 and 4 ports to blindly detect nof_ports - cell.nof_ports = 0; - cell.id = cell_id; - cell.cp = cp; - cell.nof_prb = SRSLTE_UE_MIB_NOF_PRB; + for (int i=0;isf_buffer[i] = srslte_vec_malloc(3*sizeof(cf_t)*SRSLTE_SF_LEN_PRB(SRSLTE_UE_MIB_NOF_PRB)); + } + q->nof_rx_antennas = nof_rx_antennas; - q->sf_buffer[0] = srslte_vec_malloc(3*sizeof(cf_t)*SRSLTE_SF_LEN_PRB(cell.nof_prb)); - q->nof_rx_antennas = 1; - - if (srslte_ue_mib_init(&q->ue_mib, cell)) { + if (srslte_ue_mib_init(&q->ue_mib, SRSLTE_UE_MIB_NOF_PRB)) { fprintf(stderr, "Error initiating ue_mib\n"); return SRSLTE_ERROR; } - if (srslte_ue_sync_init(&q->ue_sync, cell, recv_callback, stream_handler)) { + if (srslte_ue_sync_init_multi(&q->ue_sync, SRSLTE_UE_MIB_NOF_PRB, false, recv_callback, nof_rx_antennas, stream_handler)) { fprintf(stderr, "Error initiating ue_sync\n"); srslte_ue_mib_free(&q->ue_mib); return SRSLTE_ERROR; @@ -190,38 +213,30 @@ int srslte_ue_mib_sync_init(srslte_ue_mib_sync_t *q, return SRSLTE_SUCCESS; } -int srslte_ue_mib_sync_init_multi(srslte_ue_mib_sync_t *q, - uint32_t cell_id, - srslte_cp_t cp, - int (recv_callback)(void*, cf_t*[SRSLTE_MAX_PORTS], uint32_t, srslte_timestamp_t*), - uint32_t nof_rx_antennas, - void *stream_handler) +int srslte_ue_mib_sync_set_cell(srslte_ue_mib_sync_t *q, + uint32_t cell_id, + srslte_cp_t cp) { - srslte_cell_t cell; + srslte_cell_t cell; // If the ports are set to 0, ue_mib goes through 1, 2 and 4 ports to blindly detect nof_ports - cell.nof_ports = 0; - cell.id = cell_id; - cell.cp = cp; - cell.nof_prb = SRSLTE_UE_MIB_NOF_PRB; - - for (int i=0;isf_buffer[i] = srslte_vec_malloc(3*sizeof(cf_t)*SRSLTE_SF_LEN_PRB(cell.nof_prb)); - } - q->nof_rx_antennas = nof_rx_antennas; - - if (srslte_ue_mib_init(&q->ue_mib, cell)) { + cell.nof_ports = 0; + cell.id = cell_id; + cell.cp = cp; + cell.nof_prb = SRSLTE_UE_MIB_NOF_PRB; + + if (srslte_ue_mib_set_cell(&q->ue_mib, cell)) { fprintf(stderr, "Error initiating ue_mib\n"); return SRSLTE_ERROR; } - if (srslte_ue_sync_init_multi(&q->ue_sync, cell, recv_callback, nof_rx_antennas, stream_handler)) { + if (srslte_ue_sync_set_cell(&q->ue_sync, cell)) { fprintf(stderr, "Error initiating ue_sync\n"); srslte_ue_mib_free(&q->ue_mib); return SRSLTE_ERROR; } - srslte_ue_sync_decode_sss_on_track(&q->ue_sync, true); return SRSLTE_SUCCESS; } + void srslte_ue_mib_sync_free(srslte_ue_mib_sync_t *q) { for (int i=0;inof_rx_antennas;i++) { if (q->sf_buffer[i]) { @@ -246,7 +261,9 @@ int srslte_ue_mib_sync_decode(srslte_ue_mib_sync_t * q, int ret = SRSLTE_ERROR_INVALID_INPUTS; uint32_t nof_frames = 0; - int mib_ret = SRSLTE_UE_MIB_NOTFOUND; + int mib_ret = SRSLTE_UE_MIB_NOTFOUND; + + srslte_ue_mib_sync_reset(q); if (q != NULL) { diff --git a/lib/src/phy/ue/ue_sync.c b/lib/src/phy/ue/ue_sync.c index b5b2be3d0..967b02d63 100644 --- a/lib/src/phy/ue/ue_sync.c +++ b/lib/src/phy/ue/ue_sync.c @@ -29,6 +29,7 @@ #include #include #include +#include #include "srslte/phy/ue/ue_sync.h" @@ -122,39 +123,41 @@ int recv_callback_multi_to_single(void *h, cf_t *x[SRSLTE_MAX_PORTS], uint32_t n } int srslte_ue_sync_init(srslte_ue_sync_t *q, - srslte_cell_t cell, - int (recv_callback)(void*, void*, uint32_t,srslte_timestamp_t*), - void *stream_handler) + uint32_t max_prb, + bool search_cell, + int (recv_callback)(void*, void*, uint32_t,srslte_timestamp_t*), + void *stream_handler) { - int ret = srslte_ue_sync_init_multi(q, cell, recv_callback_multi_to_single, 1, (void*) q); + int ret = srslte_ue_sync_init_multi(q, max_prb, search_cell, recv_callback_multi_to_single, 1, (void*) q); q->recv_callback_single = recv_callback; q->stream_single = stream_handler; return ret; } int srslte_ue_sync_init_multi(srslte_ue_sync_t *q, - srslte_cell_t cell, + uint32_t max_prb, + bool search_cell, int (recv_callback)(void*, cf_t*[SRSLTE_MAX_PORTS], uint32_t,srslte_timestamp_t*), uint32_t nof_rx_antennas, void *stream_handler) { - return srslte_ue_sync_init_multi_decim(q, cell,recv_callback ,nof_rx_antennas,stream_handler,1); + return srslte_ue_sync_init_multi_decim(q, max_prb,search_cell, recv_callback ,nof_rx_antennas,stream_handler,1); } int srslte_ue_sync_init_multi_decim(srslte_ue_sync_t *q, - srslte_cell_t cell, - int (recv_callback)(void*, cf_t*[SRSLTE_MAX_PORTS], uint32_t,srslte_timestamp_t*), - uint32_t nof_rx_antennas, - void *stream_handler, - int decimate) + uint32_t max_prb, + bool search_cell, + int (recv_callback)(void*, cf_t*[SRSLTE_MAX_PORTS], uint32_t,srslte_timestamp_t*), + uint32_t nof_rx_antennas, + void *stream_handler, + int decimate) { int ret = SRSLTE_ERROR_INVALID_INPUTS; if (q != NULL && stream_handler != NULL && - srslte_nofprb_isvalid(cell.nof_prb) && nof_rx_antennas <= SRSLTE_MAX_PORTS && recv_callback != NULL) { @@ -165,43 +168,39 @@ int srslte_ue_sync_init_multi_decim(srslte_ue_sync_t *q, q->stream = stream_handler; q->recv_callback = recv_callback; q->nof_rx_antennas = nof_rx_antennas; - q->cell = cell; - q->fft_size = srslte_symbol_sz(q->cell.nof_prb); + q->fft_size = srslte_symbol_sz(max_prb); q->sf_len = SRSLTE_SF_LEN(q->fft_size); q->file_mode = false; q->correct_cfo = true; q->agc_period = 0; q->sample_offset_correct_period = DEFAULT_SAMPLE_OFFSET_CORRECT_PERIOD; q->sfo_ema = DEFAULT_SFO_EMA_COEFF; - - if (cell.id == 1000) { + + q->max_prb = max_prb; + + if (search_cell) { /* If the cell is unkown, we search PSS/SSS in 5 ms */ q->nof_recv_sf = 5; - q->decode_sss_on_track = true; - } else { /* If the cell is known, we work on a 1ms basis */ q->nof_recv_sf = 1; - q->decode_sss_on_track = true; } q->frame_len = q->nof_recv_sf*q->sf_len; - if(q->fft_size < 700 && q->decimate) - { + if(q->fft_size < 700 && q->decimate) { q->decimate = 1; } - - + if(srslte_sync_init_decim(&q->sfind, q->frame_len, q->frame_len, q->fft_size,q->decimate)) { fprintf(stderr, "Error initiating sync find\n"); goto clean_exit; } - if (cell.id == 1000) { + if (search_cell) { if(srslte_sync_init(&q->strack, q->frame_len, TRACK_FRAME_SIZE, q->fft_size)) { fprintf(stderr, "Error initiating sync track\n"); goto clean_exit; @@ -212,49 +211,7 @@ int srslte_ue_sync_init_multi_decim(srslte_ue_sync_t *q, goto clean_exit; } } - - if (cell.id == 1000) { - /* If the cell id is unknown, enable CP detection on find */ - // FIXME: CP detection not working very well. Not supporting Extended CP right now - srslte_sync_cp_en(&q->sfind, false); - srslte_sync_cp_en(&q->strack, false); - srslte_sync_set_cfo_ema_alpha(&q->sfind, 0.8); - srslte_sync_set_cfo_ema_alpha(&q->strack, 0.1); - - srslte_sync_cfo_i_detec_en(&q->sfind, false); - - q->nof_avg_find_frames = FIND_NOF_AVG_FRAMES; - srslte_sync_set_threshold(&q->sfind, 2.0); - srslte_sync_set_threshold(&q->strack, 1.2); - - } else { - srslte_sync_set_N_id_2(&q->sfind, cell.id%3); - srslte_sync_set_N_id_2(&q->strack, cell.id%3); - q->sfind.cp = cell.cp; - q->strack.cp = cell.cp; - srslte_sync_cp_en(&q->sfind, false); - srslte_sync_cp_en(&q->strack, false); - - srslte_sync_cfo_i_detec_en(&q->sfind, false); - - srslte_sync_set_cfo_ema_alpha(&q->sfind, 0.1); - srslte_sync_set_cfo_ema_alpha(&q->strack, 0.1); - - /* In find phase and if the cell is known, do not average pss correlation - * because we only capture 1 subframe and do not know where the peak is. - */ - q->nof_avg_find_frames = 1; - srslte_sync_set_em_alpha(&q->sfind, 1); - srslte_sync_set_threshold(&q->sfind, 3.0); - - srslte_sync_set_em_alpha(&q->strack, 0.2); - srslte_sync_set_threshold(&q->strack, 1.2); - - } - - srslte_ue_sync_reset(q); - ret = SRSLTE_SUCCESS; } @@ -282,6 +239,112 @@ void srslte_ue_sync_free(srslte_ue_sync_t *q) { bzero(q, sizeof(srslte_ue_sync_t)); } + +int srslte_ue_sync_set_cell(srslte_ue_sync_t *q, srslte_cell_t cell) +{ + int ret = SRSLTE_ERROR_INVALID_INPUTS; + + if (q != NULL && + srslte_nofprb_isvalid(cell.nof_prb)) + { + ret = SRSLTE_ERROR; + + if (cell.nof_prb > q->max_prb) { + fprintf(stderr, "Error in ue_sync_set_cell(): cell.nof_prb must be lower than initialized\n"); + return SRSLTE_ERROR; + } + + memcpy(&q->cell, &cell, sizeof(srslte_cell_t)); + q->fft_size = srslte_symbol_sz(q->cell.nof_prb); + q->sf_len = SRSLTE_SF_LEN(q->fft_size); + q->agc_period = 0; + + if (cell.id == 1000) { + + /* If the cell is unkown, we search PSS/SSS in 5 ms */ + q->nof_recv_sf = 5; + + q->decode_sss_on_track = true; + + } else { + + /* If the cell is known, we work on a 1ms basis */ + q->nof_recv_sf = 1; + + q->decode_sss_on_track = true; + } + + q->frame_len = q->nof_recv_sf*q->sf_len; + + if(q->fft_size < 700 && q->decimate) { + q->decimate = 1; + } + + if(srslte_sync_resize(&q->sfind, q->frame_len, q->frame_len, q->fft_size)) { + fprintf(stderr, "Error initiating sync find\n"); + return SRSLTE_ERROR; + } + if (cell.id == 1000) { + if(srslte_sync_resize(&q->strack, q->frame_len, TRACK_FRAME_SIZE, q->fft_size)) { + fprintf(stderr, "Error initiating sync track\n"); + return SRSLTE_ERROR; + } + } else { + if(srslte_sync_resize(&q->strack, q->frame_len, SRSLTE_CP_LEN_NORM(1,q->fft_size), q->fft_size)) { + fprintf(stderr, "Error initiating sync track\n"); + return SRSLTE_ERROR; + } + } + + if (cell.id == 1000) { + /* If the cell id is unknown, enable CP detection on find */ + // FIXME: CP detection not working very well. Not supporting Extended CP right now + srslte_sync_cp_en(&q->sfind, false); + srslte_sync_cp_en(&q->strack, false); + + srslte_sync_set_cfo_ema_alpha(&q->sfind, 0.8); + srslte_sync_set_cfo_ema_alpha(&q->strack, 0.1); + + srslte_sync_cfo_i_detec_en(&q->sfind, false); + + q->nof_avg_find_frames = FIND_NOF_AVG_FRAMES; + srslte_sync_set_threshold(&q->sfind, 2.0); + srslte_sync_set_threshold(&q->strack, 1.2); + + } else { + srslte_sync_set_N_id_2(&q->sfind, cell.id%3); + srslte_sync_set_N_id_2(&q->strack, cell.id%3); + q->sfind.cp = cell.cp; + q->strack.cp = cell.cp; + srslte_sync_cp_en(&q->sfind, false); + srslte_sync_cp_en(&q->strack, false); + + srslte_sync_cfo_i_detec_en(&q->sfind, false); + + srslte_sync_set_cfo_ema_alpha(&q->sfind, 0.1); + srslte_sync_set_cfo_ema_alpha(&q->strack, 0.1); + + /* In find phase and if the cell is known, do not average pss correlation + * because we only capture 1 subframe and do not know where the peak is. + */ + q->nof_avg_find_frames = 1; + srslte_sync_set_em_alpha(&q->sfind, 1); + srslte_sync_set_threshold(&q->sfind, 3.0); + + srslte_sync_set_em_alpha(&q->strack, 0.2); + srslte_sync_set_threshold(&q->strack, 1.2); + + } + + srslte_ue_sync_reset(q); + + ret = SRSLTE_SUCCESS; + } + + return ret; +} + + void srslte_ue_sync_get_last_timestamp(srslte_ue_sync_t *q, srslte_timestamp_t *timestamp) { memcpy(timestamp, &q->last_timestamp, sizeof(srslte_timestamp_t)); } @@ -642,7 +705,7 @@ int srslte_ue_sync_zerocopy_multi(srslte_ue_sync_t *q, cf_t *input_buffer[SRSLTE } if (q->correct_cfo) { for (int i=0;inof_rx_antennas;i++) { - srslte_cfo_correct(&q->sfind.cfocorr, + srslte_cfo_correct(&q->strack.cfocorr, input_buffer[i], input_buffer[i], -srslte_sync_get_cfo(&q->strack) / q->fft_size); diff --git a/lib/src/phy/ue/ue_ul.c b/lib/src/phy/ue/ue_ul.c index 08edcafe0..2792cff09 100644 --- a/lib/src/phy/ue/ue_ul.c +++ b/lib/src/phy/ue/ue_ul.c @@ -36,22 +36,20 @@ #define CURRENT_SLOTLEN_RE SRSLTE_SLOT_LEN_RE(q->cell.nof_prb, q->cell.cp) #define CURRENT_SFLEN_RE SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp) +#define MAX_SFLEN SRSLTE_SF_LEN(srslte_symbol_sz(max_prb)) -int srslte_ue_ul_init(srslte_ue_ul_t *q, - srslte_cell_t cell) +int srslte_ue_ul_init(srslte_ue_ul_t *q, + uint32_t max_prb) { int ret = SRSLTE_ERROR_INVALID_INPUTS; - if (q != NULL && - srslte_cell_isvalid(&cell)) + if (q != NULL) { ret = SRSLTE_ERROR; bzero(q, sizeof(srslte_ue_ul_t)); - q->cell = cell; - - if (srslte_ofdm_tx_init(&q->fft, q->cell.cp, q->cell.nof_prb)) { + if (srslte_ofdm_tx_init(&q->fft, SRSLTE_CP_NORM, max_prb)) { fprintf(stderr, "Error initiating FFT\n"); goto clean_exit; } @@ -60,41 +58,41 @@ int srslte_ue_ul_init(srslte_ue_ul_t *q, q->normalize_en = false; - if (srslte_cfo_init(&q->cfo, CURRENT_SFLEN)) { + if (srslte_cfo_init(&q->cfo, MAX_SFLEN)) { fprintf(stderr, "Error creating CFO object\n"); goto clean_exit; } srslte_cfo_set_tol(&q->cfo, 0); - - if (srslte_pusch_init(&q->pusch, q->cell)) { + + if (srslte_pusch_init_ue(&q->pusch, max_prb)) { fprintf(stderr, "Error creating PUSCH object\n"); goto clean_exit; } - if (srslte_pucch_init(&q->pucch, q->cell)) { + if (srslte_pucch_init(&q->pucch)) { fprintf(stderr, "Error creating PUSCH object\n"); goto clean_exit; } - if (srslte_softbuffer_tx_init(&q->softbuffer, q->cell.nof_prb)) { + if (srslte_softbuffer_tx_init(&q->softbuffer, max_prb)) { fprintf(stderr, "Error initiating soft buffer\n"); goto clean_exit; } - if (srslte_refsignal_ul_init(&q->signals, cell)) { + if (srslte_refsignal_ul_init(&q->signals, max_prb)) { fprintf(stderr, "Error initiating srslte_refsignal_ul\n"); goto clean_exit; } - q->sf_symbols = srslte_vec_malloc(CURRENT_SFLEN_RE * sizeof(cf_t)); + q->sf_symbols = srslte_vec_malloc(SRSLTE_SF_LEN_PRB(max_prb) * sizeof(cf_t)); if (!q->sf_symbols) { perror("malloc"); goto clean_exit; } - q->refsignal = srslte_vec_malloc(2 * SRSLTE_NRE * q->cell.nof_prb * sizeof(cf_t)); + q->refsignal = srslte_vec_malloc(2 * SRSLTE_NRE * max_prb * sizeof(cf_t)); if (!q->refsignal) { perror("malloc"); goto clean_exit; } - q->srs_signal = srslte_vec_malloc(SRSLTE_NRE * q->cell.nof_prb * sizeof(cf_t)); + q->srs_signal = srslte_vec_malloc(SRSLTE_NRE * max_prb * sizeof(cf_t)); if (!q->srs_signal) { perror("malloc"); goto clean_exit; @@ -102,8 +100,7 @@ int srslte_ue_ul_init(srslte_ue_ul_t *q, q->signals_pregenerated = false; ret = SRSLTE_SUCCESS; } else { - fprintf(stderr, "Invalid cell properties: Id=%d, Ports=%d, PRBs=%d\n", - cell.id, cell.nof_ports, cell.nof_prb); + fprintf(stderr, "Invalid parameters\n"); } clean_exit: @@ -115,7 +112,7 @@ clean_exit: void srslte_ue_ul_free(srslte_ue_ul_t *q) { if (q) { - srslte_ofdm_rx_free(&q->fft); + srslte_ofdm_tx_free(&q->fft); srslte_pusch_free(&q->pusch); srslte_pucch_free(&q->pucch); srslte_softbuffer_tx_free(&q->softbuffer); @@ -140,6 +137,48 @@ void srslte_ue_ul_free(srslte_ue_ul_t *q) { } } +int srslte_ue_ul_set_cell(srslte_ue_ul_t *q, + srslte_cell_t cell) +{ + int ret = SRSLTE_ERROR_INVALID_INPUTS; + + if (q != NULL && srslte_cell_isvalid(&cell)) + { + if (q->cell.id != cell.id || q->cell.nof_prb == 0) { + memcpy(&q->cell, &cell, sizeof(srslte_cell_t)); + + if (srslte_ofdm_tx_set_prb(&q->fft, q->cell.cp, q->cell.nof_prb)) { + fprintf(stderr, "Error resizing FFT\n"); + return SRSLTE_ERROR; + } + if (srslte_cfo_resize(&q->cfo, SRSLTE_SF_LEN_PRB(q->cell.nof_prb))) { + fprintf(stderr, "Error resizing CFO object\n"); + return SRSLTE_ERROR; + } + srslte_cfo_set_tol(&q->cfo, 50.0/(15000.0*srslte_symbol_sz(q->cell.nof_prb))); + if (srslte_pusch_set_cell(&q->pusch, q->cell)) { + fprintf(stderr, "Error resizing PUSCH object\n"); + return SRSLTE_ERROR; + } + if (srslte_pucch_set_cell(&q->pucch, q->cell)) { + fprintf(stderr, "Error resizing PUSCH object\n"); + return SRSLTE_ERROR; + } + if (srslte_refsignal_ul_set_cell(&q->signals, q->cell)) { + fprintf(stderr, "Error resizing srslte_refsignal_ul\n"); + return SRSLTE_ERROR; + } + q->signals_pregenerated = false; + } + ret = SRSLTE_SUCCESS; + } else { + fprintf(stderr, "Invalid cell properties: Id=%d, Ports=%d, PRBs=%d\n", + cell.id, cell.nof_ports, cell.nof_prb); + } + return ret; +} + + void srslte_ue_ul_set_cfo(srslte_ue_ul_t *q, float cur_cfo) { q->current_cfo = cur_cfo; } @@ -154,7 +193,7 @@ void srslte_ue_ul_set_normalization(srslte_ue_ul_t *q, bool enabled) q->normalize_en = enabled; } -/* Precalculate the PDSCH scramble sequences for a given RNTI. This function takes a while +/* Precalculate the PUSCH scramble sequences for a given RNTI. This function takes a while * to execute, so shall be called once the final C-RNTI has been allocated for the session. * For the connection procedure, use srslte_pusch_encode_rnti() or srslte_pusch_decode_rnti() functions */ @@ -295,7 +334,7 @@ int srslte_ue_ul_pucch_encode(srslte_ue_ul_t *q, srslte_uci_data_t uci_data, srslte_ofdm_tx_sf(&q->fft, q->sf_symbols, output_signal); if (q->cfo_en) { - srslte_cfo_correct(&q->cfo, output_signal, output_signal, q->current_cfo / srslte_symbol_sz(q->cell.nof_prb)); + srslte_cfo_correct(&q->cfo, output_signal, output_signal, q->current_cfo / srslte_symbol_sz(q->cell.nof_prb)); } if (q->normalize_en) { @@ -365,7 +404,7 @@ int srslte_ue_ul_srs_encode(srslte_ue_ul_t *q, uint32_t tti, cf_t *output_signal srslte_ofdm_tx_sf(&q->fft, q->sf_symbols, output_signal); if (q->cfo_en) { - srslte_cfo_correct(&q->cfo, output_signal, output_signal, q->current_cfo / srslte_symbol_sz(q->cell.nof_prb)); + srslte_cfo_correct(&q->cfo, output_signal, output_signal, q->current_cfo / srslte_symbol_sz(q->cell.nof_prb)); } if (q->normalize_en) { @@ -434,7 +473,7 @@ int srslte_ue_ul_pusch_encode_rnti_softbuffer(srslte_ue_ul_t *q, srslte_ofdm_tx_sf(&q->fft, q->sf_symbols, output_signal); if (q->cfo_en) { - srslte_cfo_correct(&q->cfo, output_signal, output_signal, q->current_cfo / srslte_symbol_sz(q->cell.nof_prb)); + srslte_cfo_correct(&q->cfo, output_signal, output_signal, q->current_cfo / srslte_symbol_sz(q->cell.nof_prb)); } if (q->normalize_en) { diff --git a/lib/src/phy/utils/convolution.c b/lib/src/phy/utils/convolution.c index d3b852b76..f96bdd4a2 100644 --- a/lib/src/phy/utils/convolution.c +++ b/lib/src/phy/utils/convolution.c @@ -27,6 +27,7 @@ #include #include +#include #include "srslte/phy/dft/dft.h" #include "srslte/phy/utils/vector.h" @@ -34,14 +35,17 @@ int srslte_conv_fft_cc_init(srslte_conv_fft_cc_t *q, uint32_t input_len, uint32_t filter_len) { + bzero(q, sizeof(srslte_conv_fft_cc_t)); + q->input_len = input_len; q->filter_len = filter_len; q->output_len = input_len+filter_len; + q->max_filter_len = filter_len; + q->max_input_len = input_len; q->input_fft = srslte_vec_malloc(sizeof(cf_t)*q->output_len); q->filter_fft = srslte_vec_malloc(sizeof(cf_t)*q->output_len); q->output_fft = srslte_vec_malloc(sizeof(cf_t)*q->output_len); - - + if (!q->input_fft || !q->filter_fft || !q->output_fft) { return SRSLTE_ERROR; } @@ -64,6 +68,34 @@ int srslte_conv_fft_cc_init(srslte_conv_fft_cc_t *q, uint32_t input_len, uint32_ return SRSLTE_SUCCESS; } +int srslte_conv_fft_cc_replan(srslte_conv_fft_cc_t *q, uint32_t input_len, uint32_t filter_len) { + if (input_len > q->max_input_len || filter_len > q->max_filter_len) { + fprintf(stderr, "Error in conv_fft_cc_replan(): input_len and filter_len must be lower than initialized\n"); + return -1; + } + + q->input_len = input_len; + q->filter_len = filter_len; + q->output_len = input_len+filter_len; + + if (!q->input_fft || !q->filter_fft || !q->output_fft) { + return SRSLTE_ERROR; + } + if (srslte_dft_replan(&q->input_plan,q->output_len)) { + fprintf(stderr, "Error initiating input plan\n"); + return SRSLTE_ERROR; + } + if (srslte_dft_replan(&q->filter_plan,q->output_len)) { + fprintf(stderr, "Error initiating filter plan\n"); + return SRSLTE_ERROR; + } + if (srslte_dft_replan(&q->output_plan,q->output_len)) { + fprintf(stderr, "Error initiating output plan\n"); + return SRSLTE_ERROR; + } + return SRSLTE_SUCCESS; +} + void srslte_conv_fft_cc_free(srslte_conv_fft_cc_t *q) { if (q->input_fft) { free(q->input_fft); diff --git a/lib/src/upper/gw.cc b/lib/src/upper/gw.cc index 4eba4b4d6..189c08912 100644 --- a/lib/src/upper/gw.cc +++ b/lib/src/upper/gw.cc @@ -44,11 +44,10 @@ gw::gw() :if_up(false) {} -void gw::init(srsue::pdcp_interface_gw *pdcp_, srsue::rrc_interface_gw *rrc_, srsue::ue_interface *ue_, log *gw_log_) +void gw::init(srsue::pdcp_interface_gw *pdcp_, srsue::ue_interface *ue_, log *gw_log_) { pool = byte_buffer_pool::get_instance(); pdcp = pdcp_; - rrc = rrc_; ue = ue_; gw_log = gw_log_; run_enable = true; @@ -249,11 +248,6 @@ void gw::run_thread() { gw_log->info_hex(pdu->msg, pdu->N_bytes, "TX PDU"); - while(run_enable && (!rrc->is_connected() || !rrc->have_drb())) { - rrc->connect(); - usleep(1000); - } - if (!run_enable) { break; } diff --git a/srsenb/src/phy/phch_worker.cc b/srsenb/src/phy/phch_worker.cc index eca637635..69748b11d 100644 --- a/srsenb/src/phy/phch_worker.cc +++ b/srsenb/src/phy/phch_worker.cc @@ -93,17 +93,22 @@ void phch_worker::init(phch_common* phy_, srslte::log *log_h_) fprintf(stderr, "Error allocating memory\n"); return; } - if (srslte_enb_dl_init(&enb_dl, phy->cell)) { + if (srslte_enb_dl_init(&enb_dl, phy->cell.nof_prb)) { fprintf(stderr, "Error initiating ENB DL\n"); return; } - - if (srslte_enb_ul_init(&enb_ul, - phy->cell, - NULL, - &phy->pusch_cfg, - &phy->hopping_cfg, - &phy->pucch_cfg)) + if (srslte_enb_dl_set_cell(&enb_dl, phy->cell)) { + fprintf(stderr, "Error initiating ENB DL\n"); + return; + } + srslte_enb_ul_init(&enb_ul, phy->cell.nof_prb); + + if (srslte_enb_ul_set_cell(&enb_ul, + phy->cell, + NULL, + &phy->pusch_cfg, + &phy->hopping_cfg, + &phy->pucch_cfg)) { fprintf(stderr, "Error initiating ENB DL\n"); return; diff --git a/srsue/hdr/mac/mac.h b/srsue/hdr/mac/mac.h index f6f22f334..394772703 100644 --- a/srsue/hdr/mac/mac.h +++ b/srsue/hdr/mac/mac.h @@ -163,7 +163,6 @@ private: // pointer to MAC PCAP object srslte::mac_pcap* pcap; - bool signals_pregenerated; bool is_first_ul_grant; diff --git a/srsue/hdr/phy/phch_recv.h b/srsue/hdr/phy/phch_recv.h index 0bfae26c9..c50252ae2 100644 --- a/srsue/hdr/phy/phch_recv.h +++ b/srsue/hdr/phy/phch_recv.h @@ -45,6 +45,7 @@ class phch_recv : public thread { public: phch_recv(); + ~phch_recv(); void init(srslte::radio_multi* radio_handler, mac_interface_phy *mac,rrc_interface_phy *rrc, prach *prach_buffer, srslte::thread_pool *_workers_pool, phch_common *_worker_com, srslte::log* _log_h, uint32_t nof_rx_antennas, uint32_t prio, int sync_cpu_affinity = -1); @@ -55,6 +56,7 @@ public: void set_earfcn(std::vector earfcn); + bool stop_sync(); void cell_search_start(); void cell_search_next(); bool cell_select(uint32_t earfcn, srslte_cell_t cell); @@ -75,6 +77,14 @@ private: void set_ue_sync_opts(srslte_ue_sync_t *q); void run_thread(); + void set_sampling_rate(); + bool set_frequency(); + + void cell_search_inc(); + + bool init_cell(); + void free_cell(); + bool running; srslte::radio_multi *radio_h; @@ -84,10 +94,15 @@ private: srslte::thread_pool *workers_pool; phch_common *worker_com; prach *prach_buffer; - + + // Structures for Cell Camp srslte_ue_sync_t ue_sync; srslte_ue_mib_t ue_mib; - + + // Structures for Cell Search + srslte_ue_cellsearch_t cs; + srslte_ue_mib_sync_t ue_mib_sync; + uint32_t nof_rx_antennas; cf_t *sf_buffer[SRSLTE_MAX_PORTS]; @@ -99,6 +114,8 @@ private: IDLE, CELL_SEARCH, CELL_MEASURE, CELL_SELECT, CELL_CAMP } phy_state; + bool is_in_idle; + enum { SRATE_NONE=0, SRATE_FIND, SRATE_CAMP } srate_mode; @@ -108,8 +125,7 @@ private: bool is_sfn_synched; bool started; float time_adv_sec; - bool radio_is_streaming; - uint32_t tti; + uint32_t tti; bool do_agc; float last_gain; @@ -117,8 +133,10 @@ private: uint32_t nof_tx_mutex; uint32_t tx_mutex_cnt; + uint32_t current_earfcn; + uint32_t sync_sfn_cnt; - const static uint32_t SYNC_SFN_TIMEOUT = 5000; + const static uint32_t SYNC_SFN_TIMEOUT = 100; float ul_dl_factor; int cur_earfcn_index; bool cell_search_in_progress; @@ -132,8 +150,7 @@ private: int cell_sync_sfn(); int cell_meas_rsrp(); bool cell_search(int force_N_id_2 = -1); - bool init_cell(); - void free_cell(); + bool set_cell(); }; } // namespace srsue diff --git a/srsue/hdr/phy/phch_worker.h b/srsue/hdr/phy/phch_worker.h index 669422981..bb669408e 100644 --- a/srsue/hdr/phy/phch_worker.h +++ b/srsue/hdr/phy/phch_worker.h @@ -42,11 +42,13 @@ class phch_worker : public srslte::thread_pool::worker public: phch_worker(); + ~phch_worker(); void reset(); void set_common(phch_common *phy); - bool init_cell(srslte_cell_t cell); - void free_cell(); - + bool init(uint32_t max_prb); + + bool set_cell(srslte_cell_t cell); + /* Functions used by main PHY thread */ cf_t* get_buffer(uint32_t antenna_idx); void set_tti(uint32_t tti, uint32_t tx_tti); @@ -104,14 +106,15 @@ private: /* Common objects */ phch_common *phy; - srslte_cell_t cell; - bool cell_initiated; + srslte_cell_t cell; + bool mem_initiated; + bool cell_initiated; cf_t *signal_buffer[SRSLTE_MAX_PORTS]; uint32_t tti; uint32_t tx_tti; bool pregen_enabled; uint32_t last_dl_pdcch_ncce; - bool rnti_is_set; + bool rnti_is_set; /* Objects for DL */ srslte_ue_dl_t ue_dl; diff --git a/srsue/hdr/phy/phy.h b/srsue/hdr/phy/phy.h index a2a234535..c8d88ee44 100644 --- a/srsue/hdr/phy/phy.h +++ b/srsue/hdr/phy/phy.h @@ -46,6 +46,7 @@ typedef _Complex float cf_t; class phy : public phy_interface_mac , public phy_interface_rrc + , public thread { public: phy(); @@ -57,6 +58,9 @@ public: void stop(); + void wait_initialize(); + bool is_initiated(); + void set_agc_enable(bool enabled); void get_metrics(phy_metrics_t &m); @@ -84,6 +88,7 @@ public: /********** MAC INTERFACE ********************/ /* Functions to synchronize with a cell */ bool sync_status(); // this is also RRC interface + bool sync_stop(); /* Sets a C-RNTI allowing the PHY to pregenerate signals if necessary */ void set_crnti(uint16_t rnti); @@ -130,7 +135,10 @@ public: void start_plot(); private: - + + void run_thread(); + + bool initiated; uint32_t nof_workers; const static int MAX_WORKERS = 4; @@ -139,8 +147,10 @@ private: const static int SF_RECV_THREAD_PRIO = 1; const static int WORKERS_THREAD_PRIO = 0; - srslte::radio_multi *radio_handler; - srslte::log *log_h; + srslte::radio_multi *radio_handler; + srslte::log *log_h; + srsue::mac_interface_phy *mac; + srsue::rrc_interface_phy *rrc; srslte::thread_pool workers_pool; std::vector workers; diff --git a/srsue/hdr/phy/prach.h b/srsue/hdr/phy/prach.h index 694353926..67ccc0c94 100644 --- a/srsue/hdr/phy/prach.h +++ b/srsue/hdr/phy/prach.h @@ -45,14 +45,15 @@ namespace srsue { args = NULL; config = NULL; - initiated = false; - signal_buffer = NULL; + signal_buffer = NULL; transmitted_tti = 0; - target_power_dbm = 0; + target_power_dbm = 0; + mem_initiated = false; + cell_initiated = false; } - void init(LIBLTE_RRC_PRACH_CONFIG_SIB_STRUCT *config, phy_args_t *args, srslte::log *log_h); - bool init_cell(srslte_cell_t cell); - void free_cell(); + ~prach(); + void init(LIBLTE_RRC_PRACH_CONFIG_SIB_STRUCT *config, uint32_t max_prb, phy_args_t *args, srslte::log *log_h); + bool set_cell(srslte_cell_t cell); bool prepare_to_send(uint32_t preamble_idx, int allowed_subframe = -1, float target_power_dbm = -1); bool is_ready_to_send(uint32_t current_tti); int tx_tti(); @@ -70,7 +71,8 @@ namespace srsue { srslte::log *log_h; int preamble_idx; int allowed_subframe; - bool initiated; + bool mem_initiated; + bool cell_initiated; uint32_t len; cf_t *buffer[64]; srslte_prach_t prach_obj; diff --git a/srsue/hdr/ue.h b/srsue/hdr/ue.h index 60aff8469..122b1e265 100644 --- a/srsue/hdr/ue.h +++ b/srsue/hdr/ue.h @@ -175,6 +175,7 @@ private: srsue::usim usim; srslte::logger_file logger; + //srslte::logger_stdout logger; srslte::log_filter rf_log; srslte::log_filter phy_log; srslte::log_filter mac_log; diff --git a/srsue/hdr/upper/nas.h b/srsue/hdr/upper/nas.h index 1640c9d8a..c1a481461 100644 --- a/srsue/hdr/upper/nas.h +++ b/srsue/hdr/upper/nas.h @@ -89,8 +89,6 @@ public: void plmn_found(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id, uint16_t tracking_area_code); - void cell_selected(); - // UE interface void attach_request(); diff --git a/srsue/hdr/upper/rrc.h b/srsue/hdr/upper/rrc.h index 793c2ee4f..056a3cadd 100644 --- a/srsue/hdr/upper/rrc.h +++ b/srsue/hdr/upper/rrc.h @@ -69,7 +69,6 @@ class rrc : public rrc_interface_nas, public rrc_interface_phy, public rrc_interface_mac, - public rrc_interface_gw, public rrc_interface_pdcp, public rrc_interface_rlc, public srslte::timer_callback, @@ -118,6 +117,14 @@ private: uint8_t transaction_id; bool drb_up; + uint32_t connecting_timeout; + static const uint32_t RRC_CONNECTING_TIMEOUT = 100; + + uint32_t plmn_select_timeout; + static const uint32_t RRC_PLMN_SELECT_TIMEOUT = 1000; + + uint32_t select_cell_timeout; + static const uint32_t RRC_SELECT_CELL_TIMEOUT = 500; uint8_t k_rrc_enc[32]; uint8_t k_rrc_int[32]; @@ -173,7 +180,6 @@ private: void enable_capabilities(); void plmn_search(); void plmn_select(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id); - void connect(); // PHY interface void in_sync(); diff --git a/srsue/src/mac/dl_harq.cc b/srsue/src/mac/dl_harq.cc index 685224786..7f0989982 100644 --- a/srsue/src/mac/dl_harq.cc +++ b/srsue/src/mac/dl_harq.cc @@ -177,8 +177,8 @@ void dl_harq_entity::dl_harq_process::reset() { } bool dl_harq_entity::dl_harq_process::init(uint32_t pid_, dl_harq_entity *parent) { - if (srslte_softbuffer_rx_init(&softbuffer, 110)) { - Error("Error initiating soft buffer\n"); + if (srslte_softbuffer_rx_init(&softbuffer, SRSLTE_MAX_PRB)) { + fprintf(stderr, "Error initiating soft buffer\n"); return false; } else { pid = pid_; diff --git a/srsue/src/mac/mac.cc b/srsue/src/mac/mac.cc index 5a74492e6..41a0db323 100644 --- a/srsue/src/mac/mac.cc +++ b/srsue/src/mac/mac.cc @@ -47,7 +47,6 @@ mac::mac() : ttisync(10240), { started = false; pcap = NULL; - signals_pregenerated = false; bzero(&metrics, sizeof(mac_metrics_t)); } @@ -130,8 +129,7 @@ void mac::reset() phy_h->pdcch_dl_search_reset(); phy_h->pdcch_ul_search_reset(); - signals_pregenerated = false; - is_first_ul_grant = true; + is_first_ul_grant = true; bzero(&uernti, sizeof(ue_rnti_t)); } @@ -178,18 +176,6 @@ void mac::run_thread() { ra_procedure.start_mac_order(); } ra_procedure.step(tti); - - if (ra_procedure.is_successful() && !signals_pregenerated) { - - // Configure PHY to look for UL C-RNTI grants - phy_h->pdcch_ul_search(SRSLTE_RNTI_USER, uernti.crnti); - phy_h->pdcch_dl_search(SRSLTE_RNTI_USER, uernti.crnti); - - // Pregenerate UL signals and C-RNTI scrambling sequences - Debug("Pre-computing C-RNTI scrambling sequences for C-RNTI=0x%x\n", uernti.crnti); - phy_h->set_crnti(uernti.crnti); - signals_pregenerated = true; - } } } } diff --git a/srsue/src/mac/proc_ra.cc b/srsue/src/mac/proc_ra.cc index 495c9945f..1f03cda40 100644 --- a/srsue/src/mac/proc_ra.cc +++ b/srsue/src/mac/proc_ra.cc @@ -479,6 +479,12 @@ void ra_proc::step_completition() { mux_unit->msg3_flush(); msg3_flushed = true; } + // Configure PHY to look for UL C-RNTI grants + phy_h->pdcch_ul_search(SRSLTE_RNTI_USER, rntis->crnti); + phy_h->pdcch_dl_search(SRSLTE_RNTI_USER, rntis->crnti); + + phy_h->set_crnti(rntis->crnti); + msg3_transmitted = false; state = COMPLETION_DONE; } diff --git a/srsue/src/mac/ul_harq.cc b/srsue/src/mac/ul_harq.cc index da28d62b3..970ac4276 100644 --- a/srsue/src/mac/ul_harq.cc +++ b/srsue/src/mac/ul_harq.cc @@ -206,7 +206,7 @@ void ul_harq_entity::ul_harq_process::set_harq_feedback(bool ack) { } bool ul_harq_entity::ul_harq_process::init(uint32_t pid_, ul_harq_entity* parent) { - if (srslte_softbuffer_tx_init(&softbuffer, 110)) { + if (srslte_softbuffer_tx_init(&softbuffer, SRSLTE_MAX_PRB)) { fprintf(stderr, "Error initiating soft buffer\n"); return false; } else { diff --git a/srsue/src/phy/phch_common.cc b/srsue/src/phy/phch_common.cc index 3c3987863..c65ec7c77 100644 --- a/srsue/src/phy/phch_common.cc +++ b/srsue/src/phy/phch_common.cc @@ -186,7 +186,9 @@ void phch_common::set_dl_rnti(srslte_rnti_type_t type, uint16_t rnti_value, int dl_rnti_type = type; dl_rnti_start = tti_start; dl_rnti_end = tti_end; - Debug("Set DL rnti: start=%d, end=%d, value=0x%x\n", tti_start, tti_end, rnti_value); + if (log_h) { + Debug("Set DL rnti: start=%d, end=%d, value=0x%x\n", tti_start, tti_end, rnti_value); + } } void phch_common::reset_pending_ack(uint32_t tti) { diff --git a/srsue/src/phy/phch_recv.cc b/srsue/src/phy/phch_recv.cc index 3662f4d24..6142cfaf0 100644 --- a/srsue/src/phy/phch_recv.cc +++ b/srsue/src/phy/phch_recv.cc @@ -39,12 +39,33 @@ namespace srsue { +int radio_recv_wrapper_cs(void *h, cf_t *data[SRSLTE_MAX_PORTS], uint32_t nsamples, srslte_timestamp_t *rx_time) { + srslte::radio_multi *radio_h = (srslte::radio_multi *) h; + if (radio_h->rx_now(data, nsamples, rx_time)) { + int offset = nsamples - radio_h->get_tti_len(); + if (abs(offset) < 10 && offset != 0) { + radio_h->tx_offset(offset); + } else if (nsamples < 10) { + radio_h->tx_offset(nsamples); + } + return nsamples; + } else { + return -1; + } +} + +double callback_set_rx_gain(void *h, double gain) { + srslte::radio_multi *radio_handler = (srslte::radio_multi *) h; + return radio_handler->set_rx_gain_th(gain); +} + phch_recv::phch_recv() { + bzero(&cell, sizeof(srslte_cell_t)); running = false; } -void phch_recv::init(srslte::radio_multi *_radio_handler, mac_interface_phy *_mac, rrc_interface_phy *_rrc, +void phch_recv:: init(srslte::radio_multi *_radio_handler, mac_interface_phy *_mac, rrc_interface_phy *_rrc, prach *_prach_buffer, srslte::thread_pool *_workers_pool, phch_common *_worker_com, srslte::log *_log_h, uint32_t nof_rx_antennas_, uint32_t prio, int sync_cpu_affinity) { @@ -65,11 +86,48 @@ void phch_recv::init(srslte::radio_multi *_radio_handler, mac_interface_phy *_ma sync_sfn_cnt = 0; srate_mode = SRATE_NONE; cell_search_in_progress = false; + current_earfcn = 0; for (uint32_t i = 0; i < nof_rx_antennas; i++) { sf_buffer[i] = (cf_t *) srslte_vec_malloc(sizeof(cf_t) * 3 * SRSLTE_SF_LEN_PRB(100)); } + + if (srslte_ue_cellsearch_init_multi(&cs, SRSLTE_DEFAULT_MAX_FRAMES_PSS, radio_recv_wrapper_cs, nof_rx_antennas, + radio_h)) { + Error("Initiating UE cell search\n"); + return; + } + + srslte_ue_cellsearch_set_nof_valid_frames(&cs, SRSLTE_DEFAULT_NOF_VALID_PSS_FRAMES); + + // Set options defined in expert section + set_ue_sync_opts(&cs.ue_sync); + + if (do_agc) { + srslte_ue_sync_start_agc(&cs.ue_sync, callback_set_rx_gain, last_gain); + } + + if (srslte_ue_dl_init_multi(&ue_dl_measure, SRSLTE_MAX_PRB, nof_rx_antennas)) { + Error("Initiating ue_dl_measure\n"); + return; + } + + if (srslte_ue_mib_init(&ue_mib, SRSLTE_MAX_PRB)) { + Error("Initiating UE MIB decoder\n"); + return; + } + + if (srslte_ue_sync_init_multi(&ue_sync, SRSLTE_MAX_PRB, false, radio_recv_wrapper_cs, nof_rx_antennas, radio_h)) { + Error("Initiating ue_sync\n"); + return; + } + + if (srslte_ue_mib_sync_init_multi(&ue_mib_sync, radio_recv_wrapper_cs, nof_rx_antennas, radio_h)) { + Error("Initiating UE MIB synchronization\n"); + return; + } + nof_tx_mutex = MUTEX_X_WORKER * workers_pool->get_nof_workers(); worker_com->set_nof_mutex(nof_tx_mutex); if (sync_cpu_affinity < 0) { @@ -77,44 +135,30 @@ void phch_recv::init(srslte::radio_multi *_radio_handler, mac_interface_phy *_ma } else { start_cpu(prio, sync_cpu_affinity); } - - } -void phch_recv::stop() { - running = false; - wait_thread_finish(); +phch_recv::~phch_recv() { for (uint32_t i = 0; i < nof_rx_antennas; i++) { if (sf_buffer[i]) { free(sf_buffer[i]); } } + srslte_ue_sync_free(&ue_sync); + srslte_ue_dl_free(&ue_dl_measure); + srslte_ue_mib_sync_free(&ue_mib_sync); + srslte_ue_cellsearch_free(&cs); +} + +void phch_recv::stop() { + + running = false; + wait_thread_finish(); } void phch_recv::set_agc_enable(bool enable) { do_agc = enable; } -int radio_recv_wrapper_cs(void *h, cf_t *data[SRSLTE_MAX_PORTS], uint32_t nsamples, srslte_timestamp_t *rx_time) { - srslte::radio_multi *radio_h = (srslte::radio_multi *) h; - if (radio_h->rx_now(data, nsamples, rx_time)) { - int offset = nsamples - radio_h->get_tti_len(); - if (abs(offset) < 10 && offset != 0) { - radio_h->tx_offset(offset); - } else if (nsamples < 10) { - radio_h->tx_offset(nsamples); - } - return nsamples; - } else { - return -1; - } -} - -double callback_set_rx_gain(void *h, double gain) { - srslte::radio_multi *radio_handler = (srslte::radio_multi *) h; - return radio_handler->set_rx_gain_th(gain); -} - void phch_recv::set_time_adv_sec(float _time_adv_sec) { time_adv_sec = _time_adv_sec; } @@ -147,84 +191,48 @@ void phch_recv::set_ue_sync_opts(srslte_ue_sync_t *q) { srslte_sync_set_sss_algorithm(&q->sfind, (sss_alg_t) sss_alg); } -bool phch_recv::init_cell() { +bool phch_recv::set_cell() { cell_is_set = false; - if (!srslte_ue_mib_init(&ue_mib, cell)) { - if (!srslte_ue_sync_init_multi(&ue_sync, cell, radio_recv_wrapper_cs, nof_rx_antennas, radio_h)) { - - // Set options defined in expert section - set_ue_sync_opts(&ue_sync); - - if (srslte_ue_dl_init_multi(&ue_dl_measure, cell, nof_rx_antennas)) { - Error("Setting cell: initiating ue_dl_measure\n"); - return false; - } - - for (uint32_t i = 0; i < workers_pool->get_nof_workers(); i++) { - if (!((phch_worker *) workers_pool->get_worker(i))->init_cell(cell)) { - Error("Setting cell: initiating PHCH worker\n"); - return false; - } - } - radio_h->set_tti_len(SRSLTE_SF_LEN_PRB(cell.nof_prb)); - if (do_agc) { - srslte_ue_sync_start_agc(&ue_sync, callback_set_rx_gain, last_gain); - } - srslte_ue_sync_set_cfo(&ue_sync, cellsearch_cfo); - cell_is_set = true; - } else { - Error("Error setting cell: initiating ue_sync"); - } - } else { - Error("Error setting cell: initiating ue_mib\n"); + if (srslte_ue_mib_set_cell(&ue_mib, cell)) { + Error("Setting cell: initiating ue_mib\n"); + return false; } - return cell_is_set; -} - -void phch_recv::free_cell() { - if (phy_state != IDLE) { - phy_state = IDLE; - usleep(2000); - } - - srslte_ue_sync_free(&ue_sync); - - srslte_ue_dl_free(&ue_dl_measure); - - if (cell_is_set) { - for (uint32_t i = 0; i < workers_pool->get_nof_workers(); i++) { - ((phch_worker *) workers_pool->get_worker(i))->free_cell(); - } - prach_buffer->free_cell(); - cell_is_set = false; - } -} - - -bool phch_recv::cell_search(int force_N_id_2) { - uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN]; - uint8_t bch_payload_bits[SRSLTE_BCH_PAYLOAD_LEN / 8]; - - srslte_ue_cellsearch_result_t found_cells[3]; - srslte_ue_cellsearch_t cs; - - bzero(found_cells, 3 * sizeof(srslte_ue_cellsearch_result_t)); - - if (srslte_ue_cellsearch_init_multi(&cs, SRSLTE_DEFAULT_MAX_FRAMES_PSS, radio_recv_wrapper_cs, nof_rx_antennas, - radio_h)) { - Error("Initiating UE cell search\n"); + if (srslte_ue_sync_set_cell(&ue_sync, cell)) { + Error("Setting cell: initiating ue_sync"); return false; } - srslte_ue_cellsearch_set_nof_valid_frames(&cs, SRSLTE_DEFAULT_NOF_VALID_PSS_FRAMES); - // Set options defined in expert section - set_ue_sync_opts(&cs.ue_sync); + set_ue_sync_opts(&ue_sync); - if (do_agc) { - srslte_ue_sync_start_agc(&cs.ue_sync, callback_set_rx_gain, last_gain); + if (srslte_ue_dl_set_cell(&ue_dl_measure, cell)) { + Error("Setting cell: initiating ue_dl_measure\n"); + return false; } + for (uint32_t i = 0; i < workers_pool->get_nof_workers(); i++) { + if (!((phch_worker *) workers_pool->get_worker(i))->set_cell(cell)) { + Error("Setting cell: initiating PHCH worker\n"); + return false; + } + } + radio_h->set_tti_len(SRSLTE_SF_LEN_PRB(cell.nof_prb)); + if (do_agc) { + srslte_ue_sync_start_agc(&ue_sync, callback_set_rx_gain, last_gain); + } + cell_is_set = true; + + return cell_is_set; +} + +bool phch_recv::cell_search(int force_N_id_2) { + uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN]; + + srslte_ue_cellsearch_result_t found_cells[3]; + + bzero(&cell, sizeof(srslte_cell_t)); + bzero(found_cells, 3 * sizeof(srslte_ue_cellsearch_result_t)); + if (srate_mode != SRATE_FIND) { srate_mode = SRATE_FIND; radio_h->set_rx_srate(1.92e6); @@ -245,7 +253,6 @@ bool phch_recv::cell_search(int force_N_id_2) { last_gain = srslte_agc_get_gain(&cs.ue_sync.agc); radio_h->stop_rx(); - srslte_ue_cellsearch_free(&cs); if (ret < 0) { Error("Error decoding MIB: Error searching PSS\n"); @@ -260,11 +267,8 @@ bool phch_recv::cell_search(int force_N_id_2) { cell.cp = found_cells[max_peak_cell].cp; cellsearch_cfo = found_cells[max_peak_cell].cfo; - srslte_ue_mib_sync_t ue_mib_sync; - - if (srslte_ue_mib_sync_init_multi(&ue_mib_sync, cell.id, cell.cp, radio_recv_wrapper_cs, nof_rx_antennas, - radio_h)) { - Error("Initiating UE MIB synchronization\n"); + if (srslte_ue_mib_sync_set_cell(&ue_mib_sync, cell.id, cell.cp)) { + Error("Setting UE MIB cell\n"); return false; } @@ -275,19 +279,23 @@ bool phch_recv::cell_search(int force_N_id_2) { srslte_ue_sync_start_agc(&ue_mib_sync.ue_sync, callback_set_rx_gain, last_gain); } + srslte_ue_sync_reset(&ue_mib_sync.ue_sync); srslte_ue_sync_set_cfo(&ue_mib_sync.ue_sync, cellsearch_cfo); /* Find and decode MIB */ - uint32_t sfn; int sfn_offset; radio_h->start_rx(); ret = srslte_ue_mib_sync_decode(&ue_mib_sync, - SRSLTE_DEFAULT_MAX_FRAMES_PBCH, + 40, bch_payload, &cell.nof_ports, &sfn_offset); radio_h->stop_rx(); last_gain = srslte_agc_get_gain(&ue_mib_sync.ue_sync.agc); cellsearch_cfo = srslte_ue_sync_get_cfo(&ue_mib_sync.ue_sync); - srslte_ue_mib_sync_free(&ue_mib_sync); + + srslte_ue_sync_reset(&ue_sync); + srslte_ue_sync_set_cfo(&ue_sync, cellsearch_cfo); + + Info("Setting ue_sync cfo=%f KHz\n", cellsearch_cfo/1000); if (ret == 1) { srslte_pbch_mib_unpack(bch_payload, &cell, NULL); @@ -300,87 +308,6 @@ bool phch_recv::cell_search(int force_N_id_2) { } -void phch_recv::resync_sfn() { - sync_sfn_cnt = 0; - phy_state = CELL_SELECT; -} - -void phch_recv::set_earfcn(std::vector earfcn) { - this->earfcn = earfcn; -} - -void phch_recv::cell_search_next() { - cell_search_in_progress = true; - cur_earfcn_index++; - if (cur_earfcn_index >= 0) { - if (cur_earfcn_index >= (int) earfcn.size() - 1) { - cur_earfcn_index = 0; - } - // If PHY is running, stop and free resources - free_cell(); - - float dl_freq = 1e6*srslte_band_fd(earfcn[cur_earfcn_index]); - if (dl_freq >= 0) { - log_h->info("Cell Search: Set DL EARFCN=%d, frequency=%.1f MHz, channel_index=%d\n", earfcn[cur_earfcn_index], - dl_freq / 1e6, cur_earfcn_index); - radio_h->set_rx_freq(dl_freq); - - // Start PHY cell search (finds maximum cell in frequency) - phy_state = CELL_SEARCH; - } else { - log_h->error("Cell Search: Invalid EARFCN=%d, channel_index=%d\n", earfcn[cur_earfcn_index], cur_earfcn_index); - } - } -} - -void phch_recv::cell_search_start() { - if (earfcn.size() > 0) { - cur_earfcn_index = -1; - log_h->console("Starting Cell Search procedure in %d EARFCNs...\n", earfcn.size()); - log_h->info("Cell Search: Starting procedure...\n"); - cell_search_next(); - } else { - log_h->info("Empty EARFCN list. Stopping cell search...\n"); - log_h->console("Empty EARFCN list. Stopping cell search...\n"); - } -} - -bool phch_recv::cell_select(uint32_t earfcn, srslte_cell_t cell) { - free_cell(); - - int cnt=0; - while(phy_state == CELL_SEARCH && cnt<100) { - usleep(10000); - log_h->info("PHY in CELL_SEARCH. Waiting...\n"); - } - if (phy_state==CELL_SEARCH) { - log_h->warning("PHY still in CELL_SEARCH, forcing CELL_SELECT...\n"); - } - float dl_freq = 1e6*srslte_band_fd(earfcn); - float ul_freq = 1e6*srslte_band_fu(srslte_band_ul_earfcn(earfcn)); - if (dl_freq >= 0 || ul_freq <= 0) { - log_h->info("Cell Select: Set EARFCN=%d, frequency=%.1f MHz, UL frequency=%.1f MHz\n", earfcn, dl_freq / 1e6, - ul_freq / 1e6); - radio_h->set_rx_freq(dl_freq); - radio_h->set_tx_freq(ul_freq); - - ul_dl_factor = ul_freq/dl_freq; - - cell_search_in_progress = false; - this->cell = cell; - if (init_cell()) { - phy_state = CELL_SELECT; - return true; - } else { - log_h->error("Cell Select: Initializing cell in EARFCN=%d, PCI=%d\n", earfcn, cell.id); - } - } else { - log_h->error("Cell Select: Invalid EARFCN=%d\n", earfcn); - } - return false; -} - - int phch_recv::cell_sync_sfn(void) { int ret = SRSLTE_ERROR; @@ -451,44 +378,186 @@ int phch_recv::cell_meas_rsrp() { return 0; } +void phch_recv::resync_sfn() { + radio_h->stop_rx(); + radio_h->start_rx(); + srslte_ue_mib_reset(&ue_mib); + sync_sfn_cnt = 0; + phy_state = CELL_SELECT; +} + +void phch_recv::set_earfcn(std::vector earfcn) { + this->earfcn = earfcn; +} + +bool phch_recv::stop_sync() { + Info("SYNC: Going to IDLE\n"); + phy_state = IDLE; + int cnt=0; + while(!is_in_idle && cnt<100) { + usleep(10000); + cnt++; + } + return is_in_idle; +} + +void phch_recv::cell_search_inc() +{ + cur_earfcn_index++; + Info("SYNC: Cell Search idx %d/%d\n", cur_earfcn_index, earfcn.size()); + if (cur_earfcn_index >= 0) { + if (cur_earfcn_index >= (int) earfcn.size() - 1) { + cur_earfcn_index = 0; + } + } + if (current_earfcn != earfcn[cur_earfcn_index]) { + current_earfcn = earfcn[cur_earfcn_index]; + set_frequency(); + } +} + +void phch_recv::cell_search_next() { + if (cell_search_in_progress) { + cell_search_in_progress = false; + if (!stop_sync()) { + log_h->warning("Couldn't stop sync\n"); + } + cell_search_inc(); + phy_state = CELL_SEARCH; + cell_search_in_progress = true; + } +} + +void phch_recv::cell_search_start() { + if (earfcn.size() > 0) { + cell_search_in_progress = true; + cur_earfcn_index = -1; + cell_search_next(); + log_h->console("Starting Cell Search procedure in %d EARFCNs...\n", earfcn.size()); + log_h->info("Cell Search: Starting procedure...\n"); + } else { + log_h->info("Empty EARFCN list. Stopping cell search...\n"); + log_h->console("Empty EARFCN list. Stopping cell search...\n"); + } +} + +bool phch_recv::cell_select(uint32_t earfcn, srslte_cell_t cell) { + + // Check if we are already camping in this cell + if (earfcn == current_earfcn && this->cell.id == cell.id) { + log_h->info("Cell Select: Already in Cell EARFCN=%d\n", earfcn); + cell_search_in_progress = false; + if (srate_mode != SRATE_CAMP) { + set_sampling_rate(); + } + if (phy_state != CELL_SELECT) { + resync_sfn(); + } + return true; + } else { + + cell_search_in_progress = false; + + if (!stop_sync()) { + log_h->warning("Still not in idle\n"); + } + + current_earfcn = earfcn; + + if (set_frequency()) { + this->cell = cell; + log_h->info("Cell Select: Configuring cell...\n"); + + if (set_cell()) { + log_h->info("Cell Select: Synchronizing on cell...\n"); + + resync_sfn(); + + usleep(500000); // Time offset we set start_rx to start receveing samples + return true; + } else { + log_h->error("Cell Select: Configuring cell in EARFCN=%d, PCI=%d\n", earfcn, cell.id); + } + } + return false; + } +} + +bool phch_recv::set_frequency() +{ + float dl_freq = 1e6*srslte_band_fd(current_earfcn); + float ul_freq = 1e6*srslte_band_fu(srslte_band_ul_earfcn(current_earfcn)); + if (dl_freq > 0 && ul_freq > 0) { + log_h->info("Set DL EARFCN=%d, f_dl=%.1f MHz, f_ul=%.1f MHz\n", + current_earfcn, dl_freq / 1e6, ul_freq / 1e6); + + log_h->console("Tunning to EARFCN=%d, F_dl=%.1f MHz, F_ul=%.1f MHz\n", + current_earfcn, dl_freq / 1e6, ul_freq / 1e6); + + radio_h->set_rx_freq(dl_freq); + radio_h->set_tx_freq(ul_freq); + ul_dl_factor = ul_freq / dl_freq; + + srslte_ue_sync_reset(&ue_sync); + + return true; + } else { + log_h->error("Cell Search: Invalid EARFCN=%d\n", current_earfcn); + return false; + } +} + +void phch_recv::set_sampling_rate() +{ + float srate = (float) srslte_sampling_freq_hz(cell.nof_prb); + + if (30720 % ((int) srate / 1000) == 0) { + radio_h->set_master_clock_rate(30.72e6); + } else { + radio_h->set_master_clock_rate(23.04e6); + } + + srate_mode = SRATE_CAMP; + radio_h->set_rx_srate(srate); + radio_h->set_tx_srate(srate); +} + void phch_recv::run_thread() { int sync_res; phch_worker *worker = NULL; cf_t *buffer[SRSLTE_MAX_PORTS]; + phy_state = IDLE; + is_in_idle = true; + while (running) { + if (phy_state != IDLE) { + is_in_idle = false; + Debug("SYNC state=%d\n", phy_state); + } switch (phy_state) { case CELL_SEARCH: - if (cell_search()) { - init_cell(); - float srate = (float) srslte_sampling_freq_hz(cell.nof_prb); - - if (30720 % ((int) srate / 1000) == 0) { - radio_h->set_master_clock_rate(30.72e6); - } else { - radio_h->set_master_clock_rate(23.04e6); + if (cell_search() && cell_search_in_progress) { + if (!srslte_cell_isvalid(&cell)) { + Error("Detected invalid cell\n"); + phy_state = IDLE; + break; + } + if (set_cell()) { + set_sampling_rate(); + resync_sfn(); } - log_h->info("Setting Sampling frequency %.2f MHz\n", (float) srate / 1000000); - srate_mode = SRATE_CAMP; - radio_h->set_rx_srate(srate); - radio_h->set_tx_srate(srate); - Info("SYNC: Cell found. Synchronizing...\n"); - phy_state = CELL_SELECT; - sync_sfn_cnt = 0; - srslte_ue_mib_reset(&ue_mib); + } else { + if (cell_search_in_progress) { + cell_search_inc(); + } } break; case CELL_SELECT: srslte_ue_sync_decode_sss_on_track(&ue_sync, true); - if (!radio_is_streaming) { - // Start streaming - radio_h->start_rx(); - radio_is_streaming = true; - } - switch (cell_sync_sfn()) { default: log_h->console("Going IDLE\n"); @@ -511,17 +580,17 @@ void phch_recv::run_thread() { sync_sfn_cnt++; if (sync_sfn_cnt >= SYNC_SFN_TIMEOUT) { sync_sfn_cnt = 0; - radio_h->stop_rx(); - radio_is_streaming = false; - log_h->console("Timeout while synchronizing SFN\n"); + phy_state = IDLE; log_h->warning("Timeout while synchronizing SFN\n"); } break; case CELL_MEASURE: switch(cell_meas_rsrp()) { case 1: - rrc->cell_found(earfcn[cur_earfcn_index], cell, 10*log10(measure_rsrp/1000)); phy_state = CELL_CAMP; + rrc->cell_found(earfcn[cur_earfcn_index], cell, 10*log10(measure_rsrp/1000)); + log_h->info("Measured OK. Camping on cell PCI=%d...\n", cell.id); + break; case 0: break; default: @@ -579,13 +648,11 @@ void phch_recv::run_thread() { log_h->debug("Sending in-sync to RRC\n"); } } else { - log_h->console("Sync error.\n"); log_h->error("Sync error. Sending out-of-sync to RRC\n"); // Notify RRC of out-of-sync frame rrc->out_of_sync(); worker->release(); worker_com->reset_ul(); - phy_state = CELL_SELECT; } } else { // wait_worker() only returns NULL if it's being closed. Quit now to avoid unnecessary loops here @@ -593,6 +660,10 @@ void phch_recv::run_thread() { } break; case IDLE: + if (!is_in_idle) { + radio_h->stop_rx(); + } + is_in_idle = true; usleep(1000); break; } diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index 14de9b51a..514b8eb0d 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -40,6 +40,10 @@ #ifdef ENABLE_GUI #include "srsgui/srsgui.h" #include +#include +#include +#include + void init_plots(srsue::phch_worker *worker); pthread_t plot_thread; sem_t plot_sem; @@ -57,15 +61,31 @@ phch_worker::phch_worker() : tr_exec(10240) { phy = NULL; bzero(signal_buffer, sizeof(cf_t*)*SRSLTE_MAX_PORTS); - + + mem_initiated = false; cell_initiated = false; pregen_enabled = false; - trace_enabled = false; - + trace_enabled = false; + reset(); } -void phch_worker::reset() + +phch_worker::~phch_worker() +{ + if (mem_initiated) { + for (uint32_t i=0;iargs->nof_rx_ant;i++) { + if (signal_buffer[i]) { + free(signal_buffer[i]); + } + } + srslte_ue_dl_free(&ue_dl); + srslte_ue_ul_free(&ue_ul); + mem_initiated = false; + } +} + +void phch_worker::reset() { bzero(&dl_metrics, sizeof(dl_metrics_t)); bzero(&ul_metrics, sizeof(ul_metrics_t)); @@ -86,48 +106,56 @@ void phch_worker::set_common(phch_common* phy_) { phy = phy_; } - -bool phch_worker::init_cell(srslte_cell_t cell_) + +bool phch_worker::init(uint32_t max_prb) { - memcpy(&cell, &cell_, sizeof(srslte_cell_t)); - - // ue_sync in phy.cc requires a buffer for 3 subframes + // ue_sync in phy.cc requires a buffer for 3 subframes for (uint32_t i=0;iargs->nof_rx_ant;i++) { - signal_buffer[i] = (cf_t*) srslte_vec_malloc(3 * sizeof(cf_t) * SRSLTE_SF_LEN_PRB(cell.nof_prb)); + signal_buffer[i] = (cf_t*) srslte_vec_malloc(3 * sizeof(cf_t) * SRSLTE_SF_LEN_PRB(max_prb)); if (!signal_buffer[i]) { Error("Allocating memory\n"); - return false; + return false; } } - if (srslte_ue_dl_init_multi(&ue_dl, cell, phy->args->nof_rx_ant)) { + if (srslte_ue_dl_init_multi(&ue_dl, max_prb, phy->args->nof_rx_ant)) { Error("Initiating UE DL\n"); - return false; + return false; } - - if (srslte_ue_ul_init(&ue_ul, cell)) { + + if (srslte_ue_ul_init(&ue_ul, max_prb)) { Error("Initiating UE UL\n"); - return false; + return false; } + srslte_ue_ul_set_normalization(&ue_ul, true); srslte_ue_ul_set_cfo_enable(&ue_ul, true); - - cell_initiated = true; - - return true; + + mem_initiated = true; + + return true; } -void phch_worker::free_cell() +bool phch_worker::set_cell(srslte_cell_t cell_) { - if (cell_initiated) { - for (uint32_t i=0;iargs->nof_rx_ant;i++) { - if (signal_buffer[i]) { - free(signal_buffer[i]); - } + if (cell.id != cell_.id || !cell_initiated) { + memcpy(&cell, &cell_, sizeof(srslte_cell_t)); + + if (srslte_ue_dl_set_cell(&ue_dl, cell)) { + Error("Initiating UE DL\n"); + return false; } - srslte_ue_dl_free(&ue_dl); - srslte_ue_ul_free(&ue_ul); + + if (srslte_ue_ul_set_cell(&ue_ul, cell)) { + Error("Initiating UE UL\n"); + return false; + } + srslte_ue_ul_set_normalization(&ue_ul, true); + srslte_ue_ul_set_cfo_enable(&ue_ul, true); + + cell_initiated = true; } + return true; } cf_t* phch_worker::get_buffer(uint32_t antenna_idx) @@ -375,7 +403,7 @@ bool phch_worker::decode_pdcch_dl(srsue::mac_interface_phy::mac_grant_t* grant) Error("Converting DCI message to DL grant\n"); return false; } - + /* Fill MAC grant structure */ grant->ndi = dci_unpacked.ndi; grant->pid = dci_unpacked.harq_process; @@ -426,21 +454,21 @@ bool phch_worker::decode_pdsch(srslte_ra_dl_grant_t *grant, uint8_t *payload, srslte_sch_set_max_noi(&ue_dl.pdsch.dl_sch, phy->args->pdsch_max_its); } - + #ifdef LOG_EXECTIME struct timeval t[3]; gettimeofday(&t[1], NULL); #endif - - bool ack = srslte_pdsch_decode_multi(&ue_dl.pdsch, &ue_dl.pdsch_cfg, softbuffer, ue_dl.sf_symbols_m, + + bool ack = srslte_pdsch_decode_multi(&ue_dl.pdsch, &ue_dl.pdsch_cfg, softbuffer, ue_dl.sf_symbols_m, ue_dl.ce_m, noise_estimate, rnti, payload) == 0; #ifdef LOG_EXECTIME gettimeofday(&t[2], NULL); get_time_interval(t); snprintf(timestr, 64, ", dec_time=%4d us", (int) t[0].tv_usec); #endif - - Info("PDSCH: l_crb=%2d, harq=%d, tbs=%d, mcs=%d, rv=%d, crc=%s, snr=%.1f dB, n_iter=%d%s\n", + + Info("PDSCH: l_crb=%2d, harq=%d, tbs=%d, mcs=%d, rv=%d, crc=%s, snr=%.1f dB, n_iter=%d%s\n", grant->nof_prb, harq_pid, grant->mcs.tbs/8, grant->mcs.idx, rv, ack?"OK":"KO", @@ -448,9 +476,6 @@ bool phch_worker::decode_pdsch(srslte_ra_dl_grant_t *grant, uint8_t *payload, srslte_pdsch_last_noi(&ue_dl.pdsch), timestr); - //printf("tti=%d, cfo=%f\n", tti, cfo*15000); - //srslte_vec_save_file("pdsch", signal_buffer, sizeof(cf_t)*SRSLTE_SF_LEN_PRB(cell.nof_prb)); - // Store metrics dl_metrics.mcs = grant->mcs.idx; diff --git a/srsue/src/phy/phy.cc b/srsue/src/phy/phy.cc index 9b03ab013..d96160cc7 100644 --- a/srsue/src/phy/phy.cc +++ b/srsue/src/phy/phy.cc @@ -94,44 +94,63 @@ bool phy::check_args(phy_args_t *args) return true; } -bool phy::init(srslte::radio_multi* radio_handler_, mac_interface_phy *mac, rrc_interface_phy *rrc, - srslte::log *log_h_, phy_args_t *phy_args) -{ +bool phy::init(srslte::radio_multi* radio_handler, mac_interface_phy *mac, rrc_interface_phy *rrc, + srslte::log *log_h, phy_args_t *phy_args) { mlockall(MCL_CURRENT | MCL_FUTURE); - - n_ta = 0; - log_h = log_h_; - radio_handler = radio_handler_; - + + n_ta = 0; + this->log_h = log_h; + this->radio_handler = radio_handler; + this->mac = mac; + this->rrc = rrc; + if (!phy_args) { - args = &default_args; + args = &default_args; set_default_args(args); } else { args = phy_args; } - + if (!check_args(args)) { - return false; + return false; } - - nof_workers = args->nof_phy_threads; - + + nof_workers = args->nof_phy_threads; + + initiated = false; + start(); + return true; +} + +// Initializes PHY in a thread +void phy::run_thread() { + + prach_buffer.init(&config.common.prach_cnfg, SRSLTE_MAX_PRB, args, log_h); + workers_common.init(&config, args, log_h, radio_handler, mac); + // Add workers to workers pool and start threads for (uint32_t i=0;iworker_cpu_mask); + workers[i].init(SRSLTE_MAX_PRB); + workers_pool.init_worker(i, &workers[i], WORKERS_THREAD_PRIO, args->worker_cpu_mask); } - prach_buffer.init(&config.common.prach_cnfg, args, log_h); - workers_common.init(&config, args, log_h, radio_handler, mac); - + // Warning this must be initialized after all workers have been added to the pool sf_recv.init(radio_handler, mac, rrc, &prach_buffer, &workers_pool, &workers_common, log_h, args->nof_rx_ant, SF_RECV_THREAD_PRIO, args->sync_cpu_affinity); // Disable UL signal pregeneration until the attachment enable_pregen_signals(false); - return true; + initiated = true; +} + +void phy::wait_initialize() { + wait_thread_finish(); +} + +bool phy::is_initiated() { + return initiated; } void phy::set_agc_enable(bool enabled) @@ -189,7 +208,7 @@ void phy::configure_prach_params() Debug("Configuring PRACH parameters\n"); srslte_cell_t cell; sf_recv.get_current_cell(&cell); - if (!prach_buffer.init_cell(cell)) { + if (!prach_buffer.set_cell(cell)) { Error("Configuring PRACH parameters\n"); } } else { @@ -200,8 +219,10 @@ void phy::configure_prach_params() void phy::configure_ul_params(bool pregen_disabled) { Info("PHY: Configuring UL parameters\n"); - for (uint32_t i=0;iprach_cnfg_info.prach_config_index; - uint32_t rootSeq = config->root_sequence_index; - uint32_t zeroCorrConfig = config->prach_cnfg_info.zero_correlation_zone_config; - uint32_t freq_offset = config->prach_cnfg_info.prach_freq_offset; - bool highSpeed = config->prach_cnfg_info.high_speed_flag; - - if (6 + freq_offset > cell.nof_prb) { - log_h->console("Error no space for PRACH: frequency offset=%d, N_rb_ul=%d\n", freq_offset, cell.nof_prb); - log_h->error("Error no space for PRACH: frequency offset=%d, N_rb_ul=%d\n", freq_offset, cell.nof_prb); - return false; - } - - if (srslte_prach_init(&prach_obj, srslte_symbol_sz(cell.nof_prb), - configIdx, rootSeq, highSpeed, zeroCorrConfig)) - { - Error("Initiating PRACH library\n"); - return false; - } - - len = prach_obj.N_seq + prach_obj.N_cp; - for (int i=0;i<64;i++) { - buffer[i] = (cf_t*) srslte_vec_malloc(len*sizeof(cf_t)); - if(!buffer[i]) { - return false; - } - if(srslte_prach_gen(&prach_obj, i, freq_offset, buffer[i])) { - Error("Generating PRACH preamble %d\n", i); + uint32_t configIdx = config->prach_cnfg_info.prach_config_index; + uint32_t rootSeq = config->root_sequence_index; + uint32_t zeroCorrConfig = config->prach_cnfg_info.zero_correlation_zone_config; + uint32_t freq_offset = config->prach_cnfg_info.prach_freq_offset; + bool highSpeed = config->prach_cnfg_info.high_speed_flag; + + if (6 + freq_offset > cell.nof_prb) { + log_h->console("Error no space for PRACH: frequency offset=%d, N_rb_ul=%d\n", freq_offset, cell.nof_prb); + log_h->error("Error no space for PRACH: frequency offset=%d, N_rb_ul=%d\n", freq_offset, cell.nof_prb); return false; } + + Info("PRACH: configIdx=%d, rootSequence=%d, zeroCorrelationConfig=%d, freqOffset=%d\n", + configIdx, rootSeq, zeroCorrConfig, freq_offset); + + if (srslte_prach_set_cell(&prach_obj, srslte_symbol_sz(cell.nof_prb), + configIdx, rootSeq, highSpeed, zeroCorrConfig)) { + Error("Initiating PRACH library\n"); + return false; + } + for (int i=0;i<64;i++) { + if(srslte_prach_gen(&prach_obj, i, freq_offset, buffer[i])) { + Error("Generating PRACH preamble %d\n", i); + return false; + } + } + + len = prach_obj.N_seq + prach_obj.N_cp; + transmitted_tti = -1; + cell_initiated = true; } - srslte_cfo_init(&cfo_h, len); - srslte_cfo_set_tol(&cfo_h, 0); - signal_buffer = (cf_t*) srslte_vec_malloc(len*sizeof(cf_t)); - initiated = signal_buffer?true:false; - transmitted_tti = -1; - Debug("PRACH Initiated %s\n", initiated?"OK":"KO"); + return true; + } else { + fprintf(stderr, "PRACH: Error must call init() first\n"); + return false; } - return initiated; } bool prach::prepare_to_send(uint32_t preamble_idx_, int allowed_subframe_, float target_power_dbm_) { - if (initiated && preamble_idx_ < 64) { + if (cell_initiated && preamble_idx_ < 64) { preamble_idx = preamble_idx_; target_power_dbm = target_power_dbm_; allowed_subframe = allowed_subframe_; transmitted_tti = -1; - Debug("PRACH prepare to send preamble %d\n", preamble_idx); + Debug("PRACH: prepare to send preamble %d\n", preamble_idx); return true; } else { - if (!initiated) { - Error("PRACH not initiated\n"); + if (!cell_initiated) { + Error("PRACH: Cell not configured\n"); } else if (preamble_idx_ >= 64) { - Error("Invalid preamble %d\n", preamble_idx_); + Error("PRACH: Invalid preamble %d\n", preamble_idx_); } return false; } } bool prach::is_ready_to_send(uint32_t current_tti_) { - if (initiated && preamble_idx >= 0 && preamble_idx < 64) { + if (cell_initiated && preamble_idx >= 0 && preamble_idx < 64) { // consider the number of subframes the transmission must be anticipated uint32_t current_tti = (current_tti_ + tx_advance_sf)%10240; if (srslte_prach_tti_opportunity(&prach_obj, current_tti, allowed_subframe)) { @@ -195,9 +213,9 @@ void prach::send(srslte::radio *radio_handler, float cfo, float pathloss, srslte Info("PRACH: Transmitted preamble=%d, CFO=%.2f KHz, tx_time=%f\n", preamble_idx, cfo*15, tx_time.frac_secs); - preamble_idx = -1; + preamble_idx = -1; - radio_handler->set_tx_gain(old_gain); + radio_handler->set_tx_gain(old_gain); Debug("Restoring TX gain to %.0f dB\n", old_gain); } diff --git a/srsue/src/ue.cc b/srsue/src/ue.cc index 2fd38c3c8..b6e541932 100644 --- a/srsue/src/ue.cc +++ b/srsue/src/ue.cc @@ -121,7 +121,11 @@ bool ue::init(all_args_t *args_) } // Init layers - + + // PHY initis in background, start before radio + args->expert.phy.nof_rx_ant = args->rf.nof_rx_ant; + phy.init(&radio, &mac, &rrc, &phy_log, &args->expert.phy); + /* Start Radio */ char *dev_name = NULL; if (args->rf.device_name.compare("auto")) { @@ -152,15 +156,13 @@ bool ue::init(all_args_t *args_) radio.set_manual_calibration(&args->rf_cal); // Set PHY options - args->expert.phy.nof_rx_ant = args->rf.nof_rx_ant; if (args->rf.tx_gain > 0) { args->expert.phy.ul_pwr_ctrl_en = false; } else { args->expert.phy.ul_pwr_ctrl_en = true; } - phy.init(&radio, &mac, &rrc, &phy_log, &args->expert.phy); - + if (args->rf.rx_gain < 0) { radio.start_agc(false); radio.set_tx_rx_gain_offset(10); @@ -170,7 +172,6 @@ bool ue::init(all_args_t *args_) } if (args->rf.tx_gain > 0) { radio.set_tx_gain(args->rf.tx_gain); - printf("set tx gain %f\n", args->rf.tx_gain); } else { radio.set_tx_gain(args->rf.rx_gain); std::cout << std::endl << @@ -183,19 +184,23 @@ bool ue::init(all_args_t *args_) mac.init(&phy, &rlc, &rrc, &mac_log); rlc.init(&pdcp, &rrc, this, &rlc_log, &mac); pdcp.init(&rlc, &rrc, &gw, &pdcp_log, SECURITY_DIRECTION_UPLINK); - rrc.init(&phy, &mac, &rlc, &pdcp, &nas, &usim, &mac, &rrc_log); - - rrc.set_ue_category(args->expert.ue_cateogry); - + nas.init(&usim, &rrc, &gw, &nas_log); - gw.init(&pdcp, &rrc, this, &gw_log); + gw.init(&pdcp, this, &gw_log); usim.init(&args->usim, &usim_log); + rrc.init(&phy, &mac, &rlc, &pdcp, &nas, &usim, &mac, &rrc_log); + rrc.set_ue_category(args->expert.ue_cateogry); + // Currently EARFCN list is set to only one frequency as indicated in ue.conf std::vector earfcn_list; earfcn_list.push_back(args->rf.dl_earfcn); phy.set_earfcn(earfcn_list); + printf("Waiting PHY to initialize...\n"); + phy.wait_initialize(); + phy.configure_ul_params(); + printf("\n\nRequesting NAS Attach...\n"); nas.attach_request(); diff --git a/srsue/src/upper/nas.cc b/srsue/src/upper/nas.cc index 11372e198..cb9adf3ad 100644 --- a/srsue/src/upper/nas.cc +++ b/srsue/src/upper/nas.cc @@ -107,14 +107,6 @@ void nas::plmn_found(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id, uint16_t tracking_ } } -void nas::cell_selected() { - if (state == EMM_STATE_REGISTERED_INITIATED) { - rrc->connect(); - } else { - nas_log->info("Cell selected in invalid state = %s\n", emm_state_text[state]); - } -} - bool nas::is_attached() { return state == EMM_STATE_REGISTERED; } diff --git a/srsue/src/upper/rrc.cc b/srsue/src/upper/rrc.cc index 81577cce4..8d3f7cab2 100644 --- a/srsue/src/upper/rrc.cc +++ b/srsue/src/upper/rrc.cc @@ -156,33 +156,23 @@ void rrc::plmn_search() { rrc_log->info("Starting PLMN search procedure\n"); state = RRC_STATE_PLMN_SELECTION; phy->cell_search_start(); + plmn_select_timeout = 0; } void rrc::plmn_select(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id) { rrc_log->info("PLMN %s selected\n", plmn_id_to_c_str(plmn_id).c_str()); - state = RRC_STATE_CELL_SELECTING; // Sort cells according to RSRP selected_plmn_id = plmn_id; last_selected_cell = -1; + select_cell_timeout = 0; + state = RRC_STATE_CELL_SELECTING; select_next_cell_in_plmn(); } -void rrc::connect() { - pthread_mutex_lock(&mutex); - if (RRC_STATE_CELL_SELECTED == state) { - rrc_log->info("RRC in IDLE state - sending connection request.\n"); - state = RRC_STATE_CONNECTING; - send_con_request(); - } else { - rrc_log->warning("Received connect() but cell is not selected\n"); - } - pthread_mutex_unlock(&mutex); -} - void rrc::select_next_cell_in_plmn() { for (uint32_t i = last_selected_cell + 1; i < known_cells.size(); i++) { for (uint32_t j = 0; j < known_cells[i].sib1.N_plmn_ids; j++) { @@ -196,25 +186,8 @@ void rrc::select_next_cell_in_plmn() { known_cells[i].sib1.cell_id); // Check that cell satisfies S criteria if (phy->cell_select(known_cells[i].earfcn, known_cells[i].phy_cell)) { - // Give time to the PHY to sync on the new cell - int cnt=0; - while(!phy->sync_status() && cnt<100) { - usleep(1000); - cnt++; - } - if (phy->sync_status()) { - if (!known_cells[i].has_valid_sib1) { - si_acquire_state = SI_ACQUIRE_SIB1; - } else if (!known_cells[i].has_valid_sib2) { - si_acquire_state = SI_ACQUIRE_SIB2; - } else { - si_acquire_state = SI_ACQUIRE_IDLE; - } - last_selected_cell = i; - } else { - rrc_log->warning("Selecting cell EARFCN=%d, Cell ID=0x%x: Could not synchronize\n", - known_cells[i].earfcn, known_cells[i].sib1.cell_id); - } + last_selected_cell = i; + current_cell = &known_cells[i]; return; } else { rrc_log->warning("Selecting cell EARFCN=%d, Cell ID=0x%x.\n", @@ -223,6 +196,7 @@ void rrc::select_next_cell_in_plmn() { } } } + rrc_log->info("No more known cells...\n"); } /******************************************************************************* @@ -238,6 +212,14 @@ void rrc::cell_found(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp) { current_cell = &known_cells[i]; rrc_log->info("Updating cell EARFCN=%d, PCI=%d, RSRP=%.1f dBm\n", known_cells[i].earfcn, known_cells[i].phy_cell.id, known_cells[i].rsrp); + + if (!known_cells[i].has_valid_sib1) { + si_acquire_state = SI_ACQUIRE_SIB1; + } else { + for (uint32_t i = 0; i < current_cell->sib1.N_plmn_ids; i++) { + nas->plmn_found(current_cell->sib1.plmn_id[i].id, current_cell->sib1.tracking_area_code); + } + } return; } } @@ -332,6 +314,12 @@ void rrc::write_pdu_bcch_dlsch(byte_buffer_t *pdu) { current_cell->has_valid_sib1 = true; + // Send PLMN and TAC to NAS + std::stringstream ss; + for (uint32_t i = 0; i < current_cell->sib1.N_plmn_ids; i++) { + nas->plmn_found(current_cell->sib1.plmn_id[i].id, current_cell->sib1.tracking_area_code); + } + // Jump to next state switch(state) { case RRC_STATE_CELL_SELECTING: @@ -347,12 +335,6 @@ void rrc::write_pdu_bcch_dlsch(byte_buffer_t *pdu) { si_acquire_state = SI_ACQUIRE_IDLE; } - // Send PLMN and TAC to NAS - std::stringstream ss; - for (uint32_t i = 0; i < current_cell->sib1.N_plmn_ids; i++) { - nas->plmn_found(current_cell->sib1.plmn_id[i].id, current_cell->sib1.tracking_area_code); - } - } else if (LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2 == dlsch_msg.sibs[0].sib_type && SI_ACQUIRE_SIB2 == si_acquire_state) { mac->bcch_stop_rx(); @@ -370,12 +352,10 @@ void rrc::write_pdu_bcch_dlsch(byte_buffer_t *pdu) { case RRC_STATE_CELL_SELECTING: si_acquire_state = SI_ACQUIRE_IDLE; state = RRC_STATE_CELL_SELECTED; - nas->cell_selected(); break; default: si_acquire_state = SI_ACQUIRE_IDLE; } - } } } @@ -384,7 +364,7 @@ void rrc::write_pdu_bcch_dlsch(byte_buffer_t *pdu) { // Right now, this thread only controls System Information acquisition procedure void rrc::run_thread() { uint32_t tti; - uint32_t si_win_start, si_win_len; + uint32_t si_win_start=0, si_win_len=0, last_win_start=0; uint16_t period; uint32_t nof_sib1_trials = 0; const int SIB1_SEARCH_TIMEOUT = 30; @@ -395,32 +375,94 @@ void rrc::run_thread() { // Instruct MAC to look for SIB1 tti = mac->get_current_tti(); si_win_start = sib_start_tti(tti, 2, 5); - mac->bcch_start_rx(si_win_start, 1); - rrc_log->debug("Instructed MAC to search for SIB1, win_start=%d, win_len=%d\n", - si_win_start, 1); - nof_sib1_trials++; - if (nof_sib1_trials >= SIB1_SEARCH_TIMEOUT) { - if (state == RRC_STATE_CELL_SELECTING) { - select_next_cell_in_plmn(); - si_acquire_state = SI_ACQUIRE_IDLE; - } else if (state == RRC_STATE_PLMN_SELECTION) { - phy->cell_search_next(); + if (tti > last_win_start + 10) { + last_win_start = si_win_start; + mac->bcch_start_rx(si_win_start, 1); + rrc_log->debug("Instructed MAC to search for SIB1, win_start=%d, win_len=%d\n", + si_win_start, 1); + nof_sib1_trials++; + if (nof_sib1_trials >= SIB1_SEARCH_TIMEOUT) { + if (state == RRC_STATE_CELL_SELECTING) { + select_next_cell_in_plmn(); + si_acquire_state = SI_ACQUIRE_IDLE; + } else if (state == RRC_STATE_PLMN_SELECTION) { + phy->cell_search_next(); + } + nof_sib1_trials = 0; } - nof_sib1_trials = 0; } - usleep(20000); break; case SI_ACQUIRE_SIB2: // Instruct MAC to look for SIB2 only when selecting a cell tti = mac->get_current_tti(); period = liblte_rrc_si_periodicity_num[current_cell->sib1.sched_info[0].si_periodicity]; si_win_start = sib_start_tti(tti, period, 0); - si_win_len = liblte_rrc_si_window_length_num[current_cell->sib1.si_window_length]; + if (tti > last_win_start + 10) { + last_win_start = si_win_start; + si_win_len = liblte_rrc_si_window_length_num[current_cell->sib1.si_window_length]; - mac->bcch_start_rx(si_win_start, si_win_len); - rrc_log->debug("Instructed MAC to search for SIB2, win_start=%d, win_len=%d\n", - si_win_start, si_win_len); - usleep(current_cell->sib1.si_window_length*1000); + mac->bcch_start_rx(si_win_start, si_win_len); + rrc_log->debug("Instructed MAC to search for SIB2, win_start=%d, win_len=%d\n", + si_win_start, si_win_len); + } + break; + default: + break; + } + switch(state) { + case RRC_STATE_IDLE: + if (nas->is_attached()) { + usleep(100000); + rrc_log->info("RRC IDLE: NAS is attached, re-selecting cell...\n"); + plmn_select(selected_plmn_id); + } + break; + case RRC_STATE_PLMN_SELECTION: + plmn_select_timeout++; + if (plmn_select_timeout >= RRC_PLMN_SELECT_TIMEOUT) { + rrc_log->info("RRC PLMN Search: timeout expired. Searching again\n"); + sleep(1); + rrc_log->console("RRC PLMN Search: timeout expired. Searching again\n"); + plmn_select_timeout = 0; + phy->cell_search_start(); + } + break; + case RRC_STATE_CELL_SELECTING: + if (phy->sync_status()) { + if (!current_cell->has_valid_sib1) { + si_acquire_state = SI_ACQUIRE_SIB1; + } else if (!current_cell->has_valid_sib2) { + si_acquire_state = SI_ACQUIRE_SIB2; + } else { + apply_sib2_configs(¤t_cell->sib2); + si_acquire_state = SI_ACQUIRE_IDLE; + state = RRC_STATE_CELL_SELECTED; + } + } + select_cell_timeout++; + if (select_cell_timeout >= RRC_SELECT_CELL_TIMEOUT) { + rrc_log->info("RRC Cell Selecting: timeout expired. Starting Cell Search...\n"); + state = RRC_STATE_PLMN_SELECTION; + plmn_select_timeout = 0; + phy->cell_search_start(); + } + break; + case RRC_STATE_CELL_SELECTED: + rrc_log->info("RRC Cell Selected: Sending connection request...\n"); + send_con_request(); + state = RRC_STATE_CONNECTING; + connecting_timeout = 0; + break; + case RRC_STATE_CONNECTING: + connecting_timeout++; + if (connecting_timeout >= RRC_CONNECTING_TIMEOUT) { + // Select another cell + rrc_log->info("RRC Connecting: timeout expired. Selecting next cell\n"); + state = RRC_STATE_CELL_SELECTING; + } + break; + case RRC_STATE_CONNECTED: + // Take measurements, cell reselection, etc break; default: break; @@ -442,26 +484,6 @@ void rrc::run_thread() { - - - - - -/******************************************************************************* -* -* -* -* Connection control and establishment/reestablishment procedures -* -* -* -*******************************************************************************/ - - - - - - /******************************************************************************* NAS interface *******************************************************************************/ @@ -1074,6 +1096,7 @@ void rrc::rrc_connection_release() { pthread_mutex_lock(&mutex); drb_up = false; state = RRC_STATE_IDLE; + phy->sync_stop(); set_phy_default(); set_mac_default(); mac_timers->get(t311)->run();