diff --git a/lib/include/srslte/interfaces/ue_interfaces.h b/lib/include/srslte/interfaces/ue_interfaces.h index cf8a7c861..1315b4c82 100644 --- a/lib/include/srslte/interfaces/ue_interfaces.h +++ b/lib/include/srslte/interfaces/ue_interfaces.h @@ -518,9 +518,9 @@ public: /* Cell search and selection procedures */ virtual void cell_search_start() = 0; + virtual void cell_search_stop() = 0; virtual void cell_search_next() = 0; virtual bool cell_select(uint32_t earfcn, srslte_cell_t cell) = 0; - virtual bool sync_stop() = 0; /* Is the PHY downlink synchronized? */ virtual bool sync_status() = 0; @@ -529,8 +529,6 @@ public: virtual void configure_ul_params(bool pregen_disabled = false) = 0; virtual void reset() = 0; - - virtual void resync_sfn() = 0; }; diff --git a/lib/include/srslte/radio/radio.h b/lib/include/srslte/radio/radio.h index 30d274f44..866bc4697 100644 --- a/lib/include/srslte/radio/radio.h +++ b/lib/include/srslte/radio/radio.h @@ -78,7 +78,8 @@ namespace srslte { }; bool init(char *args = NULL, char *devname = NULL); - void stop(); + void stop(); + void reset(); bool start_agc(bool tx_gain_same_rx); void set_burst_preamble(double preamble_us); @@ -170,6 +171,10 @@ namespace srslte { bool agc_enabled; int offset; uint32_t sf_len; + + char saved_args[128]; + char saved_devname[128]; + }; } diff --git a/lib/src/phy/rf/rf_uhd_imp.c b/lib/src/phy/rf/rf_uhd_imp.c index 16fb2e07e..b4aa23da5 100644 --- a/lib/src/phy/rf/rf_uhd_imp.c +++ b/lib/src/phy/rf/rf_uhd_imp.c @@ -628,9 +628,11 @@ int rf_uhd_recv_with_time_multi(void *h, } else if (error_code == UHD_RX_METADATA_ERROR_CODE_LATE_COMMAND) { log_late(handler); } else if (error_code == UHD_RX_METADATA_ERROR_CODE_TIMEOUT) { - fprintf(stderr, "Error timed out while receiving asynchronoous messages from UHD.\n"); + fprintf(stderr, "Error timed out while receiving samples from UHD.\n"); + return -1; } else if (error_code != UHD_RX_METADATA_ERROR_CODE_NONE ) { fprintf(stderr, "Error code 0x%x was returned during streaming. Aborting.\n", error_code); + return -1; } } while (n < nsamples && trials < 100); diff --git a/lib/src/phy/ue/ue_cell_search.c b/lib/src/phy/ue/ue_cell_search.c index 51b0858bb..dc35fb48c 100644 --- a/lib/src/phy/ue/ue_cell_search.c +++ b/lib/src/phy/ue/ue_cell_search.c @@ -297,7 +297,7 @@ int srslte_ue_cellsearch_scan_N_id_2(srslte_ue_cellsearch_t * q, ret = srslte_ue_sync_zerocopy_multi(&q->ue_sync, q->sf_buffer); if (ret < 0) { fprintf(stderr, "Error calling srslte_ue_sync_work()\n"); - break; + return -1; } else if (ret == 1) { /* This means a peak was found and ue_sync is now in tracking state */ ret = srslte_sync_get_cell_id(&q->ue_sync.strack); diff --git a/lib/src/phy/ue/ue_mib.c b/lib/src/phy/ue/ue_mib.c index 49ab30657..23fec7f6e 100644 --- a/lib/src/phy/ue/ue_mib.c +++ b/lib/src/phy/ue/ue_mib.c @@ -271,7 +271,7 @@ int srslte_ue_mib_sync_decode(srslte_ue_mib_sync_t * q, ret = srslte_ue_sync_zerocopy_multi(&q->ue_sync, q->sf_buffer); if (ret < 0) { fprintf(stderr, "Error calling srslte_ue_sync_work()\n"); - break; + return -1; } else if (srslte_ue_sync_get_sfidx(&q->ue_sync) == 0) { if (ret == 1) { mib_ret = srslte_ue_mib_decode(&q->ue_mib, q->sf_buffer[0], bch_payload, nof_tx_ports, sfn_offset); diff --git a/lib/src/radio/radio.cc b/lib/src/radio/radio.cc index c3592f168..3aaa8cba1 100644 --- a/lib/src/radio/radio.cc +++ b/lib/src/radio/radio.cc @@ -30,6 +30,7 @@ extern "C" { } #include "srslte/radio/radio.h" #include +#include namespace srslte { @@ -60,7 +61,10 @@ bool radio::init(char *args, char *devname) } else { printf("\nWarning burst preamble is not calibrated for device %s. Set a value manually\n\n", srslte_rf_name(&rf_device)); } - + + strncpy(saved_args, args, 128); + strncpy(saved_devname, devname, 128); + return true; } @@ -69,6 +73,16 @@ void radio::stop() srslte_rf_close(&rf_device); } +void radio::reset() +{ + printf("Resetting Radio...\n"); + srslte_rf_close(&rf_device); + sleep(3); + if (srslte_rf_open_devname(&rf_device, saved_devname, saved_args)) { + fprintf(stderr, "Error opening RF device\n"); + } +} + void radio::set_manual_calibration(rf_cal_t* calibration) { srslte_rf_cal_t tx_cal; diff --git a/srsue/hdr/phy/phch_recv.h b/srsue/hdr/phy/phch_recv.h index 784d99abc..82abfd304 100644 --- a/srsue/hdr/phy/phch_recv.h +++ b/srsue/hdr/phy/phch_recv.h @@ -52,13 +52,12 @@ public: void stop(); void set_agc_enable(bool enable); - void resync_sfn(); - void set_earfcn(std::vector earfcn); bool stop_sync(); void cell_search_start(); - void cell_search_next(); + void cell_search_stop(); + void cell_search_next(bool reset = false); bool cell_select(uint32_t earfcn, srslte_cell_t cell); uint32_t get_current_tti(); @@ -79,11 +78,16 @@ private: void set_sampling_rate(); bool set_frequency(); + void resync_sfn(); void cell_search_inc(); - bool init_cell(); - void free_cell(); + bool init_cell(); + void free_cell(); + + void stop_rx(); + void start_rx(); + bool radio_is_rx; bool running; @@ -153,7 +157,7 @@ private: int cell_sync_sfn(); int cell_meas_rsrp(); - bool cell_search(int force_N_id_2 = -1); + int cell_search(int force_N_id_2 = -1); bool set_cell(); }; diff --git a/srsue/hdr/phy/phy.h b/srsue/hdr/phy/phy.h index c8d88ee44..1d500e7f7 100644 --- a/srsue/hdr/phy/phy.h +++ b/srsue/hdr/phy/phy.h @@ -80,18 +80,17 @@ public: /********** RRC INTERFACE ********************/ void reset(); void configure_ul_params(bool pregen_disabled = false); - void resync_sfn(); void cell_search_start(); + void cell_search_stop(); void cell_search_next(); bool cell_select(uint32_t earfcn, srslte_cell_t phy_cell); /********** 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); + void set_crnti(uint16_t rnti); /* Instructs the PHY to configure using the parameters written by set_param() */ void configure_prach_params(); diff --git a/srsue/src/phy/phch_recv.cc b/srsue/src/phy/phch_recv.cc index 5b725d49f..bdfafb167 100644 --- a/srsue/src/phy/phch_recv.cc +++ b/srsue/src/phy/phch_recv.cc @@ -41,6 +41,7 @@ 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) { @@ -226,7 +227,7 @@ bool phch_recv::set_cell() { return cell_is_set; } -bool phch_recv::cell_search(int force_N_id_2) { +int 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]; @@ -238,7 +239,7 @@ bool phch_recv::cell_search(int force_N_id_2) { srate_mode = SRATE_FIND; radio_h->set_rx_srate(1.92e6); } - radio_h->start_rx(); + start_rx(); /* Find a cell in the given N_id_2 or go through the 3 of them to find the strongest */ uint32_t max_peak_cell = 0; @@ -257,13 +258,12 @@ bool phch_recv::cell_search(int force_N_id_2) { last_gain = srslte_agc_get_gain(&cs.ue_sync.agc); if (ret < 0) { - radio_h->stop_rx(); Error("SYNC: Error decoding MIB: Error searching PSS\n"); - return false; + return -1; } else if (ret == 0) { - radio_h->stop_rx(); + stop_rx(); Info("SYNC: Could not find any cell in this frequency\n"); - return false; + return 0; } // Save result cell.id = found_cells[max_peak_cell].cell_id; @@ -294,7 +294,7 @@ bool phch_recv::cell_search(int force_N_id_2) { ret = srslte_ue_mib_sync_decode(&ue_mib_sync, 40, bch_payload, &cell.nof_ports, &sfn_offset); - radio_h->stop_rx(); + 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); @@ -311,9 +311,12 @@ bool phch_recv::cell_search(int force_N_id_2) { cell.id, cell.nof_prb, cell.nof_ports, cellsearch_cfo/1000); return true; - } else { + } else if (ret == 0) { Warning("SYNC: Found PSS but could not decode PBCH\n"); - return false; + return 0; + } else { + Error("SYNC: Receiving MIB\n"); + return -1; } } @@ -391,8 +394,8 @@ int phch_recv::cell_meas_rsrp() { } void phch_recv::resync_sfn() { - radio_h->stop_rx(); - radio_h->start_rx(); + stop_rx(); + start_rx(); srslte_ue_mib_reset(&ue_mib); Info("SYNC: Starting SFN synchronization\n"); sync_sfn_cnt = 0; @@ -417,24 +420,28 @@ bool phch_recv::stop_sync() { 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; } } + usleep(100000); + Info("SYNC: Cell Search idx %d/%d\n", cur_earfcn_index, earfcn.size()); 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) { +void phch_recv::cell_search_next(bool reset) { + if (cell_search_in_progress || reset) { cell_search_in_progress = false; if (!stop_sync()) { log_h->warning("SYNC: Couldn't stop PHY\n"); } + if (reset) { + cur_earfcn_index = -1; + } cell_search_inc(); phy_state = CELL_SEARCH; cell_search_in_progress = true; @@ -443,16 +450,22 @@ void phch_recv::cell_search_next() { void phch_recv::cell_search_start() { if (earfcn.size() > 0) { - cell_search_in_progress = true; - cur_earfcn_index = -1; - cell_search_next(); - log_h->info("SYNC: Starting Cell Search procedure in %d EARFCNs...\n", earfcn.size()); + Info("SYNC: Starting Cell Search procedure in %d EARFCNs...\n", earfcn.size()); + cell_search_next(true); } else { - log_h->info("SYNC: Empty EARFCN list. Stopping cell search...\n"); + Info("SYNC: Empty EARFCN list. Stopping cell search...\n"); log_h->console("Empty EARFCN list. Stopping cell search...\n"); } } +void phch_recv::cell_search_stop() { + Info("SYNC: Stopping Cell Search procedure...\n"); + if (!stop_sync()) { + Error("SYNC: Stopping cell search\n"); + } + cell_search_in_progress = false; +} + bool phch_recv::cell_select(uint32_t earfcn, srslte_cell_t cell) { // Check if we are already camping in this cell @@ -476,6 +489,8 @@ bool phch_recv::cell_select(uint32_t earfcn, srslte_cell_t cell) { current_earfcn = earfcn; + printf("cell select called set frequency\n"); + if (set_frequency()) { this->cell = cell; log_h->info("Cell Select: Configuring cell...\n"); @@ -536,7 +551,6 @@ void phch_recv::set_sampling_rate() } void phch_recv::run_thread() { - int sync_res; phch_worker *worker = NULL; cf_t *buffer[SRSLTE_MAX_PORTS]; phy_state = IDLE; @@ -549,20 +563,28 @@ void phch_recv::run_thread() { } switch (phy_state) { case CELL_SEARCH: - if (cell_search() && cell_search_in_progress) { - if (!srslte_cell_isvalid(&cell)) { - Error("SYNC: Detected invalid cell\n"); - phy_state = IDLE; + if (cell_search_in_progress) { + switch(cell_search()) { + case 1: + if (!srslte_cell_isvalid(&cell)) { + Error("SYNC: Detected invalid cell\n"); + phy_state = IDLE; + break; + } + if (set_cell()) { + set_sampling_rate(); + resync_sfn(); + } break; - } - if (set_cell()) { - set_sampling_rate(); - resync_sfn(); - } - - } else { - if (cell_search_in_progress) { - cell_search_inc(); + case 0: + if (cell_search_in_progress) { + cell_search_inc(); + } + break; + default: + log_h->error("SYNC: Receiving frorm radio.\n"); + phy_state = IDLE; + radio_h->reset(); } } break; @@ -571,10 +593,6 @@ void phch_recv::run_thread() { srslte_ue_sync_decode_sss_on_track(&ue_sync, true); switch (cell_sync_sfn()) { - default: - log_h->console("SYNC: Going IDLE\n"); - phy_state = IDLE; - break; case 1: srslte_ue_sync_set_agc_period(&ue_sync, 20); if (!cell_search_in_progress) { @@ -588,6 +606,11 @@ void phch_recv::run_thread() { break; case 0: break; + default: + log_h->error("SYNC: Receiving frorm radio.\n"); + phy_state = IDLE; + radio_h->reset(); + break; } sync_sfn_cnt++; if (sync_sfn_cnt >= SYNC_SFN_TIMEOUT) { @@ -604,10 +627,13 @@ void phch_recv::run_thread() { rrc->cell_found(earfcn[cur_earfcn_index], cell, 10*log10(measure_rsrp/1000)); break; case 0: - break; - default: log_h->error("SYNC: Getting RSRP cell measurement.\n"); cell_search_next(); + break; + default: + log_h->error("SYNC: Receiving frorm radio.\n"); + phy_state = IDLE; + radio_h->reset(); } break; case CELL_CAMP: @@ -618,53 +644,57 @@ void phch_recv::run_thread() { buffer[i] = worker->get_buffer(i); } - sync_res = srslte_ue_sync_zerocopy_multi(&ue_sync, buffer); - if (sync_res == 1) { - - log_h->step(tti); - - Debug("SYNC: Worker %d synchronized\n", worker->get_id()); - - metrics.sfo = srslte_ue_sync_get_sfo(&ue_sync); - metrics.cfo = srslte_ue_sync_get_cfo(&ue_sync); - worker->set_cfo(ul_dl_factor * metrics.cfo / 15000); - worker_com->set_sync_metrics(metrics); - - float sample_offset = (float) srslte_ue_sync_get_sfo(&ue_sync) / 1000; - worker->set_sample_offset(sample_offset); - - /* Compute TX time: Any transmission happens in TTI4 thus advance 4 ms the reception time */ - srslte_timestamp_t rx_time, tx_time, tx_time_prach; - srslte_ue_sync_get_last_timestamp(&ue_sync, &rx_time); - srslte_timestamp_copy(&tx_time, &rx_time); - srslte_timestamp_add(&tx_time, 0, 4e-3 - time_adv_sec); - worker->set_tx_time(tx_time); - - Debug("SYNC: Setting TTI=%d, tx_mutex=%d to worker %d\n", tti, tx_mutex_cnt, worker->get_id()); - worker->set_tti(tti, tx_mutex_cnt); - tx_mutex_cnt = (tx_mutex_cnt+1) % nof_tx_mutex; - - // Check if we need to TX a PRACH - if (prach_buffer->is_ready_to_send(tti)) { - srslte_timestamp_copy(&tx_time_prach, &rx_time); - srslte_timestamp_add(&tx_time_prach, 0, prach::tx_advance_sf * 1e-3); - prach_buffer->send(radio_h, ul_dl_factor * metrics.cfo / 15000, worker_com->pathloss, tx_time_prach); - radio_h->tx_end(); - worker_com->p0_preamble = prach_buffer->get_p0_preamble(); - worker_com->cur_radio_power = SRSLTE_MIN(SRSLTE_PC_MAX, worker_com->pathloss+worker_com->p0_preamble); - } - workers_pool->start_worker(worker); - // Notify RRC in-sync every 1 frame - if ((tti % 10) == 0) { - rrc->in_sync(); - log_h->debug("SYNC: Sending in-sync to RRC\n"); - } - } else { - log_h->error("SYNC: 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(); + switch(srslte_ue_sync_zerocopy_multi(&ue_sync, buffer)) { + case 1: + + log_h->step(tti); + + Debug("SYNC: Worker %d synchronized\n", worker->get_id()); + + metrics.sfo = srslte_ue_sync_get_sfo(&ue_sync); + metrics.cfo = srslte_ue_sync_get_cfo(&ue_sync); + worker->set_cfo(ul_dl_factor * metrics.cfo / 15000); + worker_com->set_sync_metrics(metrics); + + worker->set_sample_offset(srslte_ue_sync_get_sfo(&ue_sync)/1000); + + /* Compute TX time: Any transmission happens in TTI4 thus advance 4 ms the reception time */ + srslte_timestamp_t rx_time, tx_time, tx_time_prach; + srslte_ue_sync_get_last_timestamp(&ue_sync, &rx_time); + srslte_timestamp_copy(&tx_time, &rx_time); + srslte_timestamp_add(&tx_time, 0, 4e-3 - time_adv_sec); + worker->set_tx_time(tx_time); + + Debug("SYNC: Setting TTI=%d, tx_mutex=%d to worker %d\n", tti, tx_mutex_cnt, worker->get_id()); + worker->set_tti(tti, tx_mutex_cnt); + tx_mutex_cnt = (tx_mutex_cnt+1) % nof_tx_mutex; + + // Check if we need to TX a PRACH + if (prach_buffer->is_ready_to_send(tti)) { + srslte_timestamp_copy(&tx_time_prach, &rx_time); + srslte_timestamp_add(&tx_time_prach, 0, prach::tx_advance_sf * 1e-3); + prach_buffer->send(radio_h, ul_dl_factor * metrics.cfo / 15000, worker_com->pathloss, tx_time_prach); + radio_h->tx_end(); + worker_com->p0_preamble = prach_buffer->get_p0_preamble(); + worker_com->cur_radio_power = SRSLTE_MIN(SRSLTE_PC_MAX, worker_com->pathloss+worker_com->p0_preamble); + } + workers_pool->start_worker(worker); + // Notify RRC in-sync every 1 frame + if ((tti % 10) == 0) { + rrc->in_sync(); + log_h->debug("SYNC: Sending in-sync to RRC\n"); + } + case 0: + log_h->error("SYNC: 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(); + break; + default: + log_h->error("SYNC: Receiving frorm radio.\n"); + phy_state = IDLE; + radio_h->reset(); } } else { // wait_worker() only returns NULL if it's being closed. Quit now to avoid unnecessary loops here @@ -673,7 +703,7 @@ void phch_recv::run_thread() { break; case IDLE: if (!is_in_idle) { - radio_h->stop_rx(); + stop_rx(); } is_in_idle = true; usleep(1000); @@ -682,6 +712,22 @@ void phch_recv::run_thread() { } } +void phch_recv::stop_rx() { + if (radio_is_rx) { + Info("SYNC: Stopping RX streaming\n"); + radio_h->stop_rx(); + } + radio_is_rx = false; +} + +void phch_recv::start_rx() { + if (!radio_is_rx) { + Info("SYNC: Starting RX streaming\n"); + radio_h->start_rx(); + } + radio_is_rx = true; +} + uint32_t phch_recv::get_current_tti() { return tti; } diff --git a/srsue/src/phy/phy.cc b/srsue/src/phy/phy.cc index d3933df13..828ecbf0e 100644 --- a/srsue/src/phy/phy.cc +++ b/srsue/src/phy/phy.cc @@ -232,6 +232,11 @@ void phy::cell_search_start() sf_recv.cell_search_start(); } +void phy::cell_search_stop() +{ + sf_recv.cell_search_stop(); +} + void phy::cell_search_next() { sf_recv.cell_search_next(); @@ -293,7 +298,7 @@ int phy::prach_tx_tti() void phy::reset() { - // TODO + sf_recv.stop_sync(); n_ta = 0; pdcch_dl_search_reset(); for(uint32_t i=0;i earfcns) { sf_recv.set_earfcn(earfcns); @@ -331,11 +332,6 @@ bool phy::sync_status() return sf_recv.status_is_sync(); } -bool phy::sync_stop() -{ - return sf_recv.stop_sync(); -} - void phy::set_rar_grant(uint32_t tti, uint8_t grant_payload[SRSLTE_RAR_GRANT_LEN]) { workers_common.set_rar_grant(tti, grant_payload); diff --git a/srsue/src/upper/rrc.cc b/srsue/src/upper/rrc.cc index cb7c117a3..e284e4569 100644 --- a/srsue/src/upper/rrc.cc +++ b/srsue/src/upper/rrc.cc @@ -430,6 +430,7 @@ void rrc::run_thread() { plmn_select_timeout++; if (plmn_select_timeout >= RRC_PLMN_SELECT_TIMEOUT) { rrc_log->info("RRC PLMN Search: timeout expired. Searching again\n"); + phy->cell_search_stop(); sleep(1); rrc_log->console("\nRRC PLMN Search: timeout expired. Searching again\n"); plmn_select_timeout = 0; @@ -714,7 +715,6 @@ void rrc::send_con_restablish_request() { mac->reset(); // FIXME: Cell selection should be different?? - phy->resync_sfn(); // Wait for cell re-synchronization uint32_t timeout_cnt = 0; @@ -1097,7 +1097,7 @@ void rrc::rrc_connection_release() { pthread_mutex_lock(&mutex); drb_up = false; state = RRC_STATE_IDLE; - phy->sync_stop(); + phy->reset(); set_phy_default(); set_mac_default(); mac_timers->get(t311)->run();