diff --git a/lib/examples/cell_search.c b/lib/examples/cell_search.c index 4ea89a0ca..025be3c59 100644 --- a/lib/examples/cell_search.c +++ b/lib/examples/cell_search.c @@ -199,7 +199,12 @@ int main(int argc, char **argv) { 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); + srslte_rf_info_t *rf_info = srslte_rf_get_info(&rf); + srslte_ue_sync_start_agc(&cs.ue_sync, + srslte_rf_set_rx_gain_wrapper, + rf_info->min_rx_gain, + rf_info->max_rx_gain, + cell_detect_config.init_agc); } for (freq=0;freqmin_rx_gain, + rf_info->max_rx_gain, + cell_detect_config.init_agc); } #endif #ifdef PRINT_CHANGE_SCHEDULIGN diff --git a/lib/include/srslte/phy/agc/agc.h b/lib/include/srslte/phy/agc/agc.h index ab7bb2ed7..7d49451bf 100644 --- a/lib/include/srslte/phy/agc/agc.h +++ b/lib/include/srslte/phy/agc/agc.h @@ -53,6 +53,8 @@ typedef enum SRSLTE_API { typedef struct SRSLTE_API{ float bandwidth; double gain; + double min_gain; + double max_gain; float y_out; bool lock; bool isfirst; @@ -79,6 +81,8 @@ SRSLTE_API void srslte_agc_free(srslte_agc_t *q); SRSLTE_API void srslte_agc_reset(srslte_agc_t *q); +SRSLTE_API void srslte_agc_set_gain_range(srslte_agc_t *q, double min_gain, double max_gain); + SRSLTE_API void srslte_agc_set_bandwidth(srslte_agc_t *q, float bandwidth); diff --git a/lib/include/srslte/phy/phch/pdsch.h b/lib/include/srslte/phy/phch/pdsch.h index 8a733c992..f1ecbc348 100644 --- a/lib/include/srslte/phy/phch/pdsch.h +++ b/lib/include/srslte/phy/phch/pdsch.h @@ -89,6 +89,8 @@ typedef struct SRSLTE_API { srslte_sch_t dl_sch; + void *coworker_ptr; + } srslte_pdsch_t; @@ -167,6 +169,8 @@ SRSLTE_API void srslte_pdsch_set_max_noi(srslte_pdsch_t *q, SRSLTE_API float srslte_pdsch_last_noi(srslte_pdsch_t *q); +SRSLTE_API int srslte_pdsch_enable_coworker(srslte_pdsch_t *q); + SRSLTE_API uint32_t srslte_pdsch_last_noi_cw(srslte_pdsch_t *q, uint32_t cw_idx); diff --git a/lib/include/srslte/phy/rf/rf.h b/lib/include/srslte/phy/rf/rf.h index 664d273ff..f093d1d55 100644 --- a/lib/include/srslte/phy/rf/rf.h +++ b/lib/include/srslte/phy/rf/rf.h @@ -55,6 +55,14 @@ typedef struct { float iq_q; } srslte_rf_cal_t; + +typedef struct { + double min_tx_gain; + double max_tx_gain; + double min_rx_gain; + double max_rx_gain; +} srslte_rf_info_t; + typedef struct { enum { SRSLTE_RF_ERROR_LATE, @@ -125,6 +133,8 @@ SRSLTE_API double srslte_rf_get_rx_gain(srslte_rf_t *h); SRSLTE_API double srslte_rf_get_tx_gain(srslte_rf_t *h); +SRSLTE_API srslte_rf_info_t *srslte_rf_get_info(srslte_rf_t *h); + SRSLTE_API void srslte_rf_suppress_stdout(srslte_rf_t *h); SRSLTE_API void srslte_rf_register_error_handler(srslte_rf_t *h, diff --git a/lib/include/srslte/phy/ue/ue_sync.h b/lib/include/srslte/phy/ue/ue_sync.h index 8eb18f636..45aabfbc3 100644 --- a/lib/include/srslte/phy/ue/ue_sync.h +++ b/lib/include/srslte/phy/ue/ue_sync.h @@ -199,7 +199,9 @@ SRSLTE_API void srslte_ue_sync_reset(srslte_ue_sync_t *q); SRSLTE_API int srslte_ue_sync_start_agc(srslte_ue_sync_t *q, double (set_gain_callback)(void*, double), - float init_gain_value); + double min_gain, + double max_gain, + double init_gain_value); SRSLTE_API uint32_t srslte_ue_sync_sf_len(srslte_ue_sync_t *q); diff --git a/lib/include/srslte/radio/radio.h b/lib/include/srslte/radio/radio.h index 5137bd13b..641666f93 100644 --- a/lib/include/srslte/radio/radio.h +++ b/lib/include/srslte/radio/radio.h @@ -115,6 +115,7 @@ class radio { float get_tx_gain(); float get_rx_gain(); + srslte_rf_info_t *get_info(); float get_max_tx_power(); float set_tx_power(float power); diff --git a/lib/src/phy/agc/agc.c b/lib/src/phy/agc/agc.c index ef09307c1..56277eb2e 100644 --- a/lib/src/phy/agc/agc.c +++ b/lib/src/phy/agc/agc.c @@ -45,6 +45,8 @@ int srslte_agc_init_acc(srslte_agc_t *q, srslte_agc_mode_t mode, uint32_t nof_fr bzero(q, sizeof(srslte_agc_t)); q->mode = mode; q->nof_frames = nof_frames; + q->max_gain = 90.0; + q->min_gain = 0.0; if (nof_frames > 0) { q->y_tmp = srslte_vec_malloc(sizeof(float) * nof_frames); if (!q->y_tmp) { @@ -86,6 +88,13 @@ void srslte_agc_reset(srslte_agc_t *q) { } } +void srslte_agc_set_gain_range(srslte_agc_t *q, double min_gain, double max_gain) { + if (q) { + q->min_gain = min_gain; + q->max_gain = max_gain; + } +} + void srslte_agc_set_bandwidth(srslte_agc_t *q, float bandwidth) { q->bandwidth = bandwidth; } @@ -116,19 +125,23 @@ void srslte_agc_lock(srslte_agc_t *q, bool enable) { void srslte_agc_process(srslte_agc_t *q, cf_t *signal, uint32_t len) { if (!q->lock) { - float gain_db = 10*log10(q->gain); - float gain_uhd_db = 50.0; - //float gain_uhd = 1.0; + double gain_db = 10.0 * log10(q->gain); + double gain_uhd_db = 50.0; + float y = 0; // Apply current gain to input signal if (!q->uhd_handler) { srslte_vec_sc_prod_cfc(signal, q->gain, signal, len); } else { - if (gain_db < 0) { - gain_db = 5.0; - } - if (isinf(gain_db) || isnan(gain_db)) { - gain_db = 40.0; + if (gain_db < q->min_gain) { + gain_db = q->min_gain + 5.0; + INFO("Warning: Rx signal strength is too high. Forcing minimum Rx gain %.2fdB\n", gain_db); + } else if (gain_db > q->max_gain) { + gain_db = q->max_gain; + INFO("Warning: Rx signal strength is too weak. Forcing maximum Rx gain %.2fdB\n", gain_db); + } else if (isinf(gain_db) || isnan(gain_db)) { + gain_db = (q->min_gain + q->max_gain) / 2.0; + INFO("Warning: AGC went to an unknown state. Setting Rx gain to %.2fdB\n", gain_db); } else { gain_uhd_db = q->set_gain_callback(q->uhd_handler, gain_db); q->gain = pow(10, gain_uhd_db/10); diff --git a/lib/src/phy/ch_estimation/chest_dl.c b/lib/src/phy/ch_estimation/chest_dl.c index 1970ef400..9bf7a84e9 100644 --- a/lib/src/phy/ch_estimation/chest_dl.c +++ b/lib/src/phy/ch_estimation/chest_dl.c @@ -282,7 +282,7 @@ static float estimate_noise_pilots(srslte_chest_dl_t *q, uint32_t port_id, srslt input2d[i + 1] = &q->pilot_estimates[i * nref]; } - input2d[0] = &q->tmp_noise[0]; + input2d[0] = &q->tmp_noise[nref]; if (nsymbols > 3) { srslte_vec_sc_prod_cfc(input2d[2], 2.0f, input2d[0], nref); srslte_vec_sub_ccc(input2d[0], input2d[4], input2d[0], nref); @@ -290,7 +290,7 @@ static float estimate_noise_pilots(srslte_chest_dl_t *q, uint32_t port_id, srslt srslte_vec_sc_prod_cfc(input2d[2], 1.0f, input2d[0], nref); } - input2d[nsymbols + 1] = &q->tmp_noise[nref]; + input2d[nsymbols + 1] = &q->tmp_noise[nref * 2]; if (nsymbols > 3) { srslte_vec_sc_prod_cfc(input2d[nsymbols - 1], 2.0f, input2d[nsymbols + 1], nref); srslte_vec_sub_ccc(input2d[nsymbols + 1], input2d[nsymbols - 3], input2d[nsymbols + 1], nref); diff --git a/lib/src/phy/phch/pdsch.c b/lib/src/phy/phch/pdsch.c index 315efac5a..b38cfdbd8 100644 --- a/lib/src/phy/phch/pdsch.c +++ b/lib/src/phy/phch/pdsch.c @@ -32,6 +32,9 @@ #include #include +#include +#include + #include "prb_dl.h" #include "srslte/phy/phch/pdsch.h" #include "srslte/phy/utils/debug.h" @@ -52,6 +55,39 @@ extern int indices[100000]; extern int indices_ptr; #endif + + +typedef struct { + /* Thread identifier: they must set before thread creation */ + pthread_t pthread; + uint32_t cw_idx; + uint32_t tb_idx; + void *pdsch_ptr; + bool *ack; + + /* Configuration Encoder/Decoder: they must be set before posting start semaphore */ + srslte_pdsch_cfg_t *cfg; + srslte_sch_t dl_sch; + uint16_t rnti; + + /* Encoder/Decoder data pointers: they must be set before posting start semaphore */ + uint8_t *data; + void *softbuffer; + + /* Execution status */ + int ret_status; + + /* Semaphores */ + sem_t start; + sem_t finish; + + /* Thread flags */ + bool started; + bool quit; +} srslte_pdsch_coworker_t; + +static void *srslte_pdsch_decode_thread (void *arg); + int srslte_pdsch_cp(srslte_pdsch_t *q, cf_t *input, cf_t *output, srslte_ra_dl_grant_t *grant, uint32_t lstart_grant, uint32_t nsubframe, bool put) { uint32_t s, n, l, lp, lstart, lend, nof_refs; @@ -283,7 +319,26 @@ int srslte_pdsch_init_enb(srslte_pdsch_t *q, uint32_t max_prb) return pdsch_init(q, max_prb, false, 0); } +static void srslte_pdsch_disable_coworker(srslte_pdsch_t *q) { + srslte_pdsch_coworker_t *h = (srslte_pdsch_coworker_t *) q->coworker_ptr; + if (h) { + /* Stop threads */ + h->quit = true; + sem_post(&h->start); + + pthread_join(h->pthread, NULL); + pthread_detach(h->pthread); + + srslte_sch_free(&h->dl_sch); + + free(h); + + q->coworker_ptr = NULL; + } +} + void srslte_pdsch_free(srslte_pdsch_t *q) { + srslte_pdsch_disable_coworker(q); for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) { @@ -612,9 +667,9 @@ static int srslte_pdsch_codeword_encode(srslte_pdsch_t *q, srslte_pdsch_cfg_t *c return SRSLTE_SUCCESS; } -static int srslte_pdsch_codeword_decode(srslte_pdsch_t *q, srslte_pdsch_cfg_t *cfg, - srslte_softbuffer_rx_t *softbuffer, uint16_t rnti, uint8_t *data, - uint32_t codeword_idx, uint32_t tb_idx, bool *ack) { +static int srslte_pdsch_codeword_decode(srslte_pdsch_t *q, srslte_pdsch_cfg_t *cfg, srslte_sch_t *dl_sch, + srslte_softbuffer_rx_t *softbuffer, uint16_t rnti, uint8_t *data, + uint32_t codeword_idx, uint32_t tb_idx, bool *ack) { srslte_ra_nbits_t *nbits = &cfg->nbits[tb_idx]; srslte_ra_mcs_t *mcs = &cfg->grant.mcs[tb_idx]; uint32_t rv = cfg->rv[tb_idx]; @@ -673,7 +728,7 @@ static int srslte_pdsch_codeword_decode(srslte_pdsch_t *q, srslte_pdsch_cfg_t *c } /* Return */ - ret = srslte_dlsch_decode2(&q->dl_sch, cfg, softbuffer, q->e[codeword_idx], data, tb_idx); + ret = srslte_dlsch_decode2(dl_sch, cfg, softbuffer, q->e[codeword_idx], data, tb_idx); q->last_nof_iterations[codeword_idx] = srslte_sch_last_noi(&q->dl_sch); @@ -694,6 +749,35 @@ static int srslte_pdsch_codeword_decode(srslte_pdsch_t *q, srslte_pdsch_cfg_t *c return ret; } +static void *srslte_pdsch_decode_thread(void *arg) { + srslte_pdsch_coworker_t *q = (srslte_pdsch_coworker_t *) arg; + + INFO("[PDSCH Coworker] waiting for data\n"); + + sem_wait(&q->start); + while (!q->quit) { + q->ret_status = srslte_pdsch_codeword_decode(q->pdsch_ptr, + q->cfg, + &q->dl_sch, + q->softbuffer, + q->rnti, + q->data, + q->cw_idx, + q->tb_idx, + q->ack); + + /* Post finish semaphore */ + sem_post(&q->finish); + + /* Wait for next loop */ + sem_wait(&q->start); + } + sem_post(&q->finish); + + pthread_exit(NULL); + return q; +} + /** Decodes the PDSCH from the received symbols */ int srslte_pdsch_decode(srslte_pdsch_t *q, @@ -776,11 +860,37 @@ int srslte_pdsch_decode(srslte_pdsch_t *q, /* Decode only if transport block is enabled and the default ACK is not true */ if (cfg->grant.tb_en[tb_idx]) { if (!acks[tb_idx]) { - int ret = srslte_pdsch_codeword_decode(q, cfg, softbuffers[tb_idx], rnti, data[tb_idx], cw_idx, tb_idx, &acks[tb_idx]); + int ret = SRSLTE_SUCCESS; + if (SRSLTE_RA_DL_GRANT_NOF_TB(&cfg->grant) > 1 && tb_idx == 0 && q->coworker_ptr) { + srslte_pdsch_coworker_t *h = (srslte_pdsch_coworker_t *) q->coworker_ptr; + + h->pdsch_ptr = q; + h->cfg = cfg; + h->softbuffer = softbuffers[tb_idx]; + h->rnti = rnti; + h->data = data[tb_idx]; + h->cw_idx = cw_idx; + h->tb_idx = tb_idx; + h->ack = &acks[tb_idx]; + h->dl_sch.max_iterations = q->dl_sch.max_iterations; + h->started = true; + sem_post(&h->start); + + } else { + ret = srslte_pdsch_codeword_decode(q, + cfg, + &q->dl_sch, + softbuffers[tb_idx], + rnti, + data[tb_idx], + cw_idx, + tb_idx, + &acks[tb_idx]); + } /* Check if there has been any execution error */ if (ret) { - return ret; + /* Do Nothing */ } } @@ -788,6 +898,21 @@ int srslte_pdsch_decode(srslte_pdsch_t *q, } } + if (q->coworker_ptr) { + srslte_pdsch_coworker_t *h = (srslte_pdsch_coworker_t *) q->coworker_ptr; + if (h->started) { + int err = sem_wait(&h->finish); + if (err) { + printf("SCH coworker: %s (nof_tb=%d)\n", strerror(errno), SRSLTE_RA_DL_GRANT_NOF_TB(&cfg->grant)); + } + if (h->ret_status) { + ERROR("PDSCH Coworker Decoder: Error decoding"); + } + + h->started = false; + } + } + pdsch_decode_debug(q, cfg, sf_symbols, ce); return SRSLTE_SUCCESS; @@ -945,6 +1070,45 @@ float srslte_pdsch_last_noi(srslte_pdsch_t *q) { } } +int srslte_pdsch_enable_coworker(srslte_pdsch_t *q) { + int ret = SRSLTE_SUCCESS; + + if (!q->coworker_ptr) { + srslte_pdsch_coworker_t *h = calloc(sizeof(srslte_pdsch_coworker_t), 1); + + if (!h) { + ERROR("Allocating coworker"); + ret = SRSLTE_ERROR; + goto clean; + } + q->coworker_ptr = h; + + if (srslte_sch_init(&h->dl_sch)) { + ERROR("Initiating DL SCH"); + ret = SRSLTE_ERROR; + goto clean; + } + + if (sem_init(&h->start, 0, 0)) { + ERROR("Creating semaphore"); + ret = SRSLTE_ERROR; + goto clean; + } + if (sem_init(&h->finish, 0, 0)) { + ERROR("Creating semaphore"); + ret = SRSLTE_ERROR; + goto clean; + } + pthread_create(&h->pthread, NULL, srslte_pdsch_decode_thread, (void *) h); + } + + clean: + if (ret) { + srslte_pdsch_disable_coworker(q); + } + return ret; +} + uint32_t srslte_pdsch_last_noi_cw(srslte_pdsch_t *q, uint32_t cw_idx) { return q->last_nof_iterations[cw_idx]; } diff --git a/lib/src/phy/phch/test/pdsch_test.c b/lib/src/phy/phch/test/pdsch_test.c index f823698f9..c4f8953a5 100644 --- a/lib/src/phy/phch/test/pdsch_test.c +++ b/lib/src/phy/phch/test/pdsch_test.c @@ -60,6 +60,7 @@ int rv_idx[SRSLTE_MAX_CODEWORDS] = {0, 1}; uint16_t rnti = 1234; uint32_t nof_rx_antennas = 1; bool tb_cw_swap = false; +bool enable_coworker = false; uint32_t pmi = 0; char *input_file = NULL; @@ -79,12 +80,13 @@ void usage(char *prog) { printf("\t-a nof_rx_antennas [Default %d]\n", nof_rx_antennas); printf("\t-p pmi (multiplex only) [Default %d]\n", pmi); printf("\t-w Swap Transport Blocks\n"); + printf("\t-j Enable PDSCH decoder coworker\n"); printf("\t-v [set srslte_verbose to debug, default none]\n"); } void parse_args(int argc, char **argv) { int opt; - while ((opt = getopt(argc, argv, "fmMcsrtRFpnawvx")) != -1) { + while ((opt = getopt(argc, argv, "fmMcsrtRFpnawvxj")) != -1) { switch(opt) { case 'f': input_file = argv[optind]; @@ -129,6 +131,9 @@ void parse_args(int argc, char **argv) { case 'w': tb_cw_swap = true; break; + case 'j': + enable_coworker = true; + break; case 'v': srslte_verbose++; break; @@ -470,6 +475,10 @@ int main(int argc, char **argv) { int r=0; srslte_pdsch_set_max_noi(&pdsch_rx, 10); + if (enable_coworker) { + srslte_pdsch_enable_coworker(&pdsch_rx); + } + gettimeofday(&t[1], NULL); for (k = 0; k < M; k++) { #ifdef DO_OFDM diff --git a/lib/src/phy/rf/rf_blade_imp.c b/lib/src/phy/rf/rf_blade_imp.c index 4a8173f29..4f624f8ce 100644 --- a/lib/src/phy/rf/rf_blade_imp.c +++ b/lib/src/phy/rf/rf_blade_imp.c @@ -45,6 +45,7 @@ typedef struct { int16_t tx_buffer[CONVERT_BUFFER_SIZE]; bool rx_stream_enabled; bool tx_stream_enabled; + srslte_rf_info_t info; } rf_blade_handler_t; srslte_rf_error_handler_t blade_error_handler = NULL; @@ -220,7 +221,14 @@ int rf_blade_open(char *args, void **h) return status; } handler->rx_stream_enabled = false; - handler->tx_stream_enabled = false; + handler->tx_stream_enabled = false; + + /* Set info structure */ + handler->info.min_tx_gain = BLADERF_TXVGA2_GAIN_MIN; + handler->info.max_tx_gain = BLADERF_TXVGA2_GAIN_MAX; + handler->info.min_rx_gain = BLADERF_RXVGA2_GAIN_MIN; + handler->info.max_rx_gain = BLADERF_RXVGA2_GAIN_MAX; + return 0; } @@ -336,6 +344,19 @@ double rf_blade_get_tx_gain(void *h) return gain; // Add txvga1 } +srslte_rf_info_t *rf_blade_get_info(void *h) +{ + + srslte_rf_info_t *info = NULL; + + if (h) { + rf_blade_handler_t *handler = (rf_blade_handler_t*) h; + + info = &handler->info; + } + return info; +} + double rf_blade_set_rx_freq(void *h, double freq) { rf_blade_handler_t *handler = (rf_blade_handler_t*) h; diff --git a/lib/src/phy/rf/rf_blade_imp.h b/lib/src/phy/rf/rf_blade_imp.h index 1a2cf1250..6c8c04c43 100644 --- a/lib/src/phy/rf/rf_blade_imp.h +++ b/lib/src/phy/rf/rf_blade_imp.h @@ -76,6 +76,8 @@ SRSLTE_API double rf_blade_get_rx_gain(void *h); SRSLTE_API double rf_blade_get_tx_gain(void *h); +SRSLTE_API srslte_rf_info_t *rf_blade_get_info(void *h); + SRSLTE_API void rf_blade_suppress_stdout(void *h); SRSLTE_API void rf_blade_register_error_handler(void *h, diff --git a/lib/src/phy/rf/rf_dev.h b/lib/src/phy/rf/rf_dev.h index f800fb398..80b5125e4 100644 --- a/lib/src/phy/rf/rf_dev.h +++ b/lib/src/phy/rf/rf_dev.h @@ -47,6 +47,7 @@ typedef struct { double (*srslte_rf_set_tx_gain)(void *h, double gain); double (*srslte_rf_get_rx_gain)(void *h); double (*srslte_rf_get_tx_gain)(void *h); + srslte_rf_info_t *(*srslte_rf_get_info)(void *h); double (*srslte_rf_set_rx_freq)(void *h, double freq); double (*srslte_rf_set_tx_srate)(void *h, double freq); double (*srslte_rf_set_tx_freq)(void *h, double freq); @@ -93,6 +94,7 @@ static rf_dev_t dev_uhd = { rf_uhd_set_tx_gain, rf_uhd_get_rx_gain, rf_uhd_get_tx_gain, + rf_uhd_get_info, rf_uhd_set_rx_freq, rf_uhd_set_tx_srate, rf_uhd_set_tx_freq, @@ -132,6 +134,7 @@ static rf_dev_t dev_blade = { rf_blade_set_tx_gain, rf_blade_get_rx_gain, rf_blade_get_tx_gain, + rf_blade_get_info, rf_blade_set_rx_freq, rf_blade_set_tx_srate, rf_blade_set_tx_freq, @@ -170,6 +173,7 @@ static rf_dev_t dev_soapy = { rf_soapy_set_tx_gain, rf_soapy_get_rx_gain, rf_soapy_get_tx_gain, + rf_soapy_get_info, rf_soapy_set_rx_freq, rf_soapy_set_tx_srate, rf_soapy_set_tx_freq, diff --git a/lib/src/phy/rf/rf_imp.c b/lib/src/phy/rf/rf_imp.c index c3d8d9516..eec44ef30 100644 --- a/lib/src/phy/rf/rf_imp.c +++ b/lib/src/phy/rf/rf_imp.c @@ -227,6 +227,15 @@ double srslte_rf_get_tx_gain(srslte_rf_t *rf) return ((rf_dev_t*) rf->dev)->srslte_rf_get_tx_gain(rf->handler); } +srslte_rf_info_t *srslte_rf_get_info(srslte_rf_t *rf) { + srslte_rf_info_t *ret = NULL; + if (((rf_dev_t*) rf->dev)->srslte_rf_get_info) { + ret = ((rf_dev_t*) rf->dev)->srslte_rf_get_info(rf->handler); + } + return ret; +} + + double srslte_rf_set_rx_freq(srslte_rf_t *rf, double freq) { return ((rf_dev_t*) rf->dev)->srslte_rf_set_rx_freq(rf->handler, freq); diff --git a/lib/src/phy/rf/rf_soapy_imp.c b/lib/src/phy/rf/rf_soapy_imp.c index 9a45ff8f1..15854682f 100644 --- a/lib/src/phy/rf/rf_soapy_imp.c +++ b/lib/src/phy/rf/rf_soapy_imp.c @@ -46,6 +46,7 @@ typedef struct { SoapySDRStream *txStream; bool tx_stream_active; bool rx_stream_active; + srslte_rf_info_t info; } rf_soapy_handler_t; @@ -259,6 +260,14 @@ int rf_soapy_open_multi(char *args, void **h, uint32_t nof_rx_antennas) printf(" - %s\n", sensors[i]); } + /* Set static radio info */ + SoapySDRRange tx_range = SoapySDRDevice_getGainRange(handler->device, SOAPY_SDR_TX, 0); + SoapySDRRange rx_range = SoapySDRDevice_getGainRange(handler->device, SOAPY_SDR_RX, 0); + handler->info.min_tx_gain = tx_range.minimum; + handler->info.max_tx_gain = tx_range.maximum; + handler->info.min_rx_gain = rx_range.minimum; + handler->info.max_rx_gain = rx_range.maximum; + return SRSLTE_SUCCESS; } @@ -361,6 +370,17 @@ double rf_soapy_get_tx_gain(void *h) } +srslte_rf_info_t * rf_soapy_get_info(void *h) +{ + srslte_rf_info_t *info = NULL; + if (h) { + rf_soapy_handler_t *handler = (rf_soapy_handler_t*) h; + info = &handler->info; + } + return info; +} + + double rf_soapy_set_rx_freq(void *h, double freq) { rf_soapy_handler_t *handler = (rf_soapy_handler_t*) h; diff --git a/lib/src/phy/rf/rf_soapy_imp.h b/lib/src/phy/rf/rf_soapy_imp.h index 4974157d1..a2ccf106a 100644 --- a/lib/src/phy/rf/rf_soapy_imp.h +++ b/lib/src/phy/rf/rf_soapy_imp.h @@ -75,6 +75,8 @@ SRSLTE_API double rf_soapy_set_tx_gain(void *h, SRSLTE_API double rf_soapy_get_tx_gain(void *h); +SRSLTE_API srslte_rf_info_t *rf_soapy_get_info(void *h); + SRSLTE_API void rf_soapy_suppress_stdout(void *h); SRSLTE_API void rf_soapy_register_error_handler(void *h, srslte_rf_error_handler_t error_handler); diff --git a/lib/src/phy/rf/rf_uhd_imp.c b/lib/src/phy/rf/rf_uhd_imp.c index d9099d5f1..a0548347e 100644 --- a/lib/src/phy/rf/rf_uhd_imp.c +++ b/lib/src/phy/rf/rf_uhd_imp.c @@ -46,7 +46,7 @@ typedef struct { uhd_rx_metadata_handle rx_md, rx_md_first; uhd_tx_metadata_handle tx_md; - uhd_meta_range_handle rx_gain_range; + srslte_rf_info_t info; size_t rx_nof_samples; size_t tx_nof_samples; double tx_rate; @@ -572,9 +572,20 @@ int rf_uhd_open_multi(char *args, void **h, uint32_t nof_channels) uhd_rx_streamer_max_num_samps(handler->rx_stream, &handler->rx_nof_samples); uhd_tx_streamer_max_num_samps(handler->tx_stream, &handler->tx_nof_samples); - - uhd_meta_range_make(&handler->rx_gain_range); - uhd_usrp_get_rx_gain_range(handler->usrp, "", 0, handler->rx_gain_range); + + uhd_meta_range_handle rx_gain_range = NULL; + uhd_meta_range_make(&rx_gain_range); + uhd_usrp_get_rx_gain_range(handler->usrp, "", 0, rx_gain_range); + uhd_meta_range_start(rx_gain_range, &handler->info.min_rx_gain); + uhd_meta_range_stop(rx_gain_range, &handler->info.max_rx_gain); + uhd_meta_range_free(&rx_gain_range); + + uhd_meta_range_handle tx_gain_range = NULL; + uhd_meta_range_make(&tx_gain_range); + uhd_usrp_get_tx_gain_range(handler->usrp, "", 0, tx_gain_range); + uhd_meta_range_start(tx_gain_range, &handler->info.min_tx_gain); + uhd_meta_range_stop(tx_gain_range, &handler->info.max_tx_gain); + uhd_meta_range_free(&tx_gain_range); // Make metadata objects for RX/TX uhd_rx_metadata_make(&handler->rx_md); @@ -582,13 +593,7 @@ int rf_uhd_open_multi(char *args, void **h, uint32_t nof_channels) uhd_tx_metadata_make(&handler->tx_md, false, 0, 0, false, false); // Set starting gain to half maximum in case of using AGC - uhd_meta_range_handle gain_range; - uhd_meta_range_make(&gain_range); - uhd_usrp_get_rx_gain_range(handler->usrp, "", 0, gain_range); - double max_gain; - uhd_meta_range_stop(gain_range, &max_gain); - rf_uhd_set_rx_gain(handler, max_gain*0.7); - uhd_meta_range_free(&gain_range); + rf_uhd_set_rx_gain(handler, handler->info.max_tx_gain*0.7); #if HAVE_ASYNC_THREAD if (start_async_thread) { @@ -620,7 +625,6 @@ int rf_uhd_close(void *h) uhd_tx_metadata_free(&handler->tx_md); uhd_rx_metadata_free(&handler->rx_md_first); uhd_rx_metadata_free(&handler->rx_md); - uhd_meta_range_free(&handler->rx_gain_range); handler->async_thread_running = false; pthread_join(handler->async_thread, NULL); @@ -722,6 +726,16 @@ double rf_uhd_get_tx_gain(void *h) return gain; } +srslte_rf_info_t *rf_uhd_get_info(void *h) +{ + srslte_rf_info_t *info = NULL; + if (h) { + rf_uhd_handler_t *handler = (rf_uhd_handler_t*) h; + info = &handler->info; + } + return info; +} + double rf_uhd_set_rx_freq(void *h, double freq) { uhd_tune_request_t tune_request = { diff --git a/lib/src/phy/rf/rf_uhd_imp.h b/lib/src/phy/rf/rf_uhd_imp.h index 23501a3ca..6bc0f22f7 100644 --- a/lib/src/phy/rf/rf_uhd_imp.h +++ b/lib/src/phy/rf/rf_uhd_imp.h @@ -81,6 +81,8 @@ SRSLTE_API double rf_uhd_get_rx_gain(void *h); SRSLTE_API double rf_uhd_get_tx_gain(void *h); +SRSLTE_API srslte_rf_info_t *rf_uhd_get_info(void *h); + SRSLTE_API void rf_uhd_suppress_stdout(void *h); SRSLTE_API void rf_uhd_register_error_handler(void *h, srslte_rf_error_handler_t error_handler); diff --git a/lib/src/phy/ue/ue_sync.c b/lib/src/phy/ue/ue_sync.c index a0ae46990..2b146aed9 100644 --- a/lib/src/phy/ue/ue_sync.c +++ b/lib/src/phy/ue/ue_sync.c @@ -140,11 +140,15 @@ void srslte_ue_sync_reset(srslte_ue_sync_t *q) { q->frame_find_cnt = 0; } - -int srslte_ue_sync_start_agc(srslte_ue_sync_t *q, double (set_gain_callback)(void*, double), float init_gain_value) { +int srslte_ue_sync_start_agc(srslte_ue_sync_t *q, + double (set_gain_callback)(void *, double), + double min_gain, + double max_gain, + double init_gain_value) { int n = srslte_agc_init_uhd(&q->agc, SRSLTE_AGC_MODE_PEAK_AMPLITUDE, 0, set_gain_callback, q->stream); q->do_agc = n==0?true:false; if (q->do_agc) { + srslte_agc_set_gain_range(&q->agc, min_gain, max_gain); srslte_agc_set_gain(&q->agc, init_gain_value); srslte_ue_sync_set_agc_period(q, 4); } diff --git a/lib/src/radio/radio.cc b/lib/src/radio/radio.cc index 622e32589..1b114968b 100644 --- a/lib/src/radio/radio.cc +++ b/lib/src/radio/radio.cc @@ -470,6 +470,9 @@ void radio::register_error_handler(srslte_rf_error_handler_t h) srslte_rf_register_error_handler(&rf_device, h); } +srslte_rf_info_t *radio::get_info() { + return srslte_rf_get_info(&rf_device); +} } diff --git a/srsue/hdr/phy/phch_worker.h b/srsue/hdr/phy/phch_worker.h index ff167d20e..ce53e8833 100644 --- a/srsue/hdr/phy/phch_worker.h +++ b/srsue/hdr/phy/phch_worker.h @@ -45,6 +45,7 @@ public: ~phch_worker(); void reset(); void set_common(phch_common *phy); + void enable_pdsch_coworker(); bool init(uint32_t max_prb, srslte::log *log, srslte::log *log_phy_lib_h, chest_feedback_itf *chest_loop); bool set_cell(srslte_cell_t cell); diff --git a/srsue/hdr/phy/phy.h b/srsue/hdr/phy/phy.h index 38bcb6d8b..fa3ed2fee 100644 --- a/srsue/hdr/phy/phy.h +++ b/srsue/hdr/phy/phy.h @@ -153,8 +153,9 @@ private: bool initiated; uint32_t nof_workers; - - const static int MAX_WORKERS = 4; + uint32_t nof_coworkers; + + const static int MAX_WORKERS = 3; const static int DEFAULT_WORKERS = 2; const static int SF_RECV_THREAD_PRIO = 1; diff --git a/srsue/src/phy/phch_recv.cc b/srsue/src/phy/phch_recv.cc index ddeccd183..7e41c6836 100644 --- a/srsue/src/phy/phch_recv.cc +++ b/srsue/src/phy/phch_recv.cc @@ -625,7 +625,12 @@ void phch_recv::set_agc_enable(bool enable) do_agc = enable; if (do_agc) { if (running && radio_h) { - srslte_ue_sync_start_agc(&ue_sync, callback_set_rx_gain, radio_h->get_rx_gain()); + srslte_rf_info_t *rf_info = radio_h->get_info(); + srslte_ue_sync_start_agc(&ue_sync, + callback_set_rx_gain, + rf_info->min_rx_gain, + rf_info->max_rx_gain, + radio_h->get_rx_gain()); search_p.set_agc_enable(true); } else { fprintf(stderr, "Error setting AGC: PHY not initiatec\n"); @@ -893,7 +898,12 @@ float phch_recv::search::get_last_cfo() void phch_recv::search::set_agc_enable(bool enable) { if (enable) { - srslte_ue_sync_start_agc(&ue_mib_sync.ue_sync, callback_set_rx_gain, p->radio_h->get_rx_gain()); + srslte_rf_info_t *rf_info = p->radio_h->get_info(); + srslte_ue_sync_start_agc(&ue_mib_sync.ue_sync, + callback_set_rx_gain, + rf_info->min_rx_gain, + rf_info->max_rx_gain, + p->radio_h->get_rx_gain()); } else { fprintf(stderr, "Error stop AGC not implemented\n"); } diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index 1a7df429b..e6e7727fd 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -103,6 +103,10 @@ void phch_worker::reset() rssi_read_cnt = 0; } +void phch_worker::enable_pdsch_coworker() { + srslte_pdsch_enable_coworker(&ue_dl.pdsch); +} + void phch_worker::set_common(phch_common* phy_) { phy = phy_; diff --git a/srsue/src/phy/phy.cc b/srsue/src/phy/phy.cc index 20f40f4b6..508dd5dfb 100644 --- a/srsue/src/phy/phy.cc +++ b/srsue/src/phy/phy.cc @@ -104,7 +104,7 @@ void phy::set_default_args(phy_args_t *args) bool phy::check_args(phy_args_t *args) { - if (args->nof_phy_threads > 3) { + if (args->nof_phy_threads > MAX_WORKERS * 2) { log_h->console("Error in PHY args: nof_phy_threads must be 1, 2 or 3\n"); return false; } @@ -139,6 +139,10 @@ bool phy::init(srslte::radio_multi* radio_handler, mac_interface_phy *mac, rrc_i } nof_workers = args->nof_phy_threads; + if (nof_workers > MAX_WORKERS) { + nof_coworkers = SRSLTE_MIN(nof_workers - MAX_WORKERS, MAX_WORKERS); + nof_workers = MAX_WORKERS; + } this->log_phy_lib_h = (srslte::log*) log_vec[nof_workers]; srslte_phy_log_register_handler(this, srslte_phy_handler); @@ -160,6 +164,10 @@ void phy::run_thread() { workers_pool.init_worker(i, &workers[i], WORKERS_THREAD_PRIO, args->worker_cpu_mask); } + for (uint32_t i=0;inof_rx_ant, SF_RECV_THREAD_PRIO, args->sync_cpu_affinity); diff --git a/srsue/src/ue.cc b/srsue/src/ue.cc index faf36ae70..6fa4bed6c 100644 --- a/srsue/src/ue.cc +++ b/srsue/src/ue.cc @@ -55,6 +55,11 @@ ue::~ue() bool ue::init(all_args_t *args_) { args = args_; + int nof_phy_threads = args->expert.phy.nof_phy_threads; + if (nof_phy_threads > 3) { + nof_phy_threads = 3; + } + if (!args->log.filename.compare("stdout")) { logger = &logger_stdout; } else { @@ -66,7 +71,7 @@ bool ue::init(all_args_t *args_) { rf_log.init("RF ", logger); // Create array of pointers to phy_logs - for (int i=0;iexpert.phy.nof_phy_threads;i++) { + for (int i=0;iexpert.phy.nof_phy_threads;i++) { + for (int i=0;iset_level(level(args->log.phy_level)); } @@ -95,7 +100,7 @@ bool ue::init(all_args_t *args_) { sprintf(tmp, "PHY_LIB"); lib_log->init(tmp, logger, true); phy_log.push_back(lib_log); - ((srslte::log_filter*) phy_log[args->expert.phy.nof_phy_threads])->set_level(level(args->log.phy_lib_level)); + ((srslte::log_filter*) phy_log[nof_phy_threads])->set_level(level(args->log.phy_lib_level)); mac_log.set_level(level(args->log.mac_level)); @@ -106,7 +111,7 @@ bool ue::init(all_args_t *args_) { gw_log.set_level(level(args->log.gw_level)); usim_log.set_level(level(args->log.usim_level)); - for (int i=0;iexpert.phy.nof_phy_threads + 1;i++) { + for (int i=0;iset_hex_limit(args->log.phy_hex_limit); } mac_log.set_hex_limit(args->log.mac_hex_limit);