From b12d69b439fced0426ffc292fc36b6da8dbd1568 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Thu, 21 Sep 2017 21:43:24 +0200 Subject: [PATCH] Set default TX mode to continuous and fixed uplink synchronization (radio set offset concurrent access) --- lib/include/srslte/radio/radio.h | 14 +++-------- lib/src/phy/rf/rf_uhd_imp.c | 20 +++++++++------ lib/src/phy/rf/uhd_c_api.cpp | 6 +++++ lib/src/phy/rf/uhd_c_api.h | 1 + lib/src/phy/ue/ue_sync.c | 2 +- lib/src/radio/radio.cc | 30 +++++++++-------------- srsue/hdr/mac/ul_harq.h | 1 + srsue/hdr/phy/phch_common.h | 5 ++-- srsue/hdr/phy/phch_recv.h | 10 ++++++-- srsue/hdr/phy/phch_worker.h | 6 +++-- srsue/src/phy/phch_common.cc | 2 -- srsue/src/phy/phch_recv.cc | 42 +++++++++++++++++++------------- srsue/src/phy/phch_worker.cc | 19 +++++++++------ 13 files changed, 89 insertions(+), 69 deletions(-) diff --git a/lib/include/srslte/radio/radio.h b/lib/include/srslte/radio/radio.h index 866bc4697..329dd825a 100644 --- a/lib/include/srslte/radio/radio.h +++ b/lib/include/srslte/radio/radio.h @@ -57,8 +57,7 @@ namespace srslte { bzero(&end_of_burst_time, sizeof(srslte_timestamp_t)); bzero(zeros, burst_preamble_max_samples*sizeof(cf_t)); - sf_len = 0; - burst_preamble_sec = 0; + burst_preamble_sec = 0; is_start_of_burst = false; burst_preamble_samples = 0; burst_preamble_time_rounded = 0; @@ -72,9 +71,7 @@ namespace srslte { rx_freq = 0; trace_enabled = false; tti = 0; - agc_enabled = false; - offset = 0; - + agc_enabled = false; }; bool init(char *args = NULL, char *devname = NULL); @@ -124,9 +121,8 @@ namespace srslte { void stop_rx(); void set_tti(uint32_t tti); - void tx_offset(int offset); - void set_tti_len(uint32_t sf_len); - uint32_t get_tti_len(); + + bool is_first_of_burst(); void register_error_handler(srslte_rf_error_handler_t h); @@ -169,8 +165,6 @@ namespace srslte { bool trace_enabled; uint32_t tti; 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 0c7bd53ff..95287a628 100644 --- a/lib/src/phy/rf/rf_uhd_imp.c +++ b/lib/src/phy/rf/rf_uhd_imp.c @@ -710,11 +710,11 @@ int rf_uhd_send_timed_multi(void *h, } size_t txd_samples; - if (has_time_spec) { - uhd_tx_metadata_set_time_spec(&handler->tx_md, secs, frac_secs); - } - int trials = 0; + int trials = 0; if (blocking) { + if (has_time_spec) { + uhd_tx_metadata_set_time_spec(&handler->tx_md, secs, frac_secs); + } int n = 0; cf_t *data_c[4]; for (int i = 0; i < 4; i++) { @@ -722,8 +722,8 @@ int rf_uhd_send_timed_multi(void *h, } do { size_t tx_samples = handler->tx_nof_samples; - - // First packet is start of burst if so defined, others are never + + // First packet is start of burst if so defined, others are never if (n == 0) { uhd_tx_metadata_set_start(&handler->tx_md, is_start_of_burst); } else { @@ -760,9 +760,15 @@ int rf_uhd_send_timed_multi(void *h, for (int i = 0; i < 4; i++) { buffs_ptr[i] = data[i]; } + uhd_tx_metadata_set_has_time_spec(&handler->tx_md, is_start_of_burst); uhd_tx_metadata_set_start(&handler->tx_md, is_start_of_burst); uhd_tx_metadata_set_end(&handler->tx_md, is_end_of_burst); - return uhd_tx_streamer_send(handler->tx_stream, buffs_ptr, nsamples, &handler->tx_md, 0.0, &txd_samples); + uhd_error error = uhd_tx_streamer_send(handler->tx_stream, buffs_ptr, nsamples, &handler->tx_md, 3.0, &txd_samples); + if (error) { + fprintf(stderr, "Error sending to UHD: %d\n", error); + return -1; + } + return txd_samples; } } diff --git a/lib/src/phy/rf/uhd_c_api.cpp b/lib/src/phy/rf/uhd_c_api.cpp index da348c17b..d98c3c92a 100644 --- a/lib/src/phy/rf/uhd_c_api.cpp +++ b/lib/src/phy/rf/uhd_c_api.cpp @@ -38,6 +38,12 @@ void uhd_tx_metadata_set_start(uhd_tx_metadata_handle *md, bool is_start_of_burs (*md)->tx_metadata_cpp.start_of_burst = is_start_of_burst; } +void uhd_tx_metadata_set_has_time_spec(uhd_tx_metadata_handle *md, bool has_time_spec) +{ + (*md)->tx_metadata_cpp.has_time_spec = has_time_spec; +} + + void uhd_tx_metadata_set_end(uhd_tx_metadata_handle *md, bool is_end_of_burst) { (*md)->tx_metadata_cpp.end_of_burst = is_end_of_burst; diff --git a/lib/src/phy/rf/uhd_c_api.h b/lib/src/phy/rf/uhd_c_api.h index 15bb5f33c..8f6cb2743 100644 --- a/lib/src/phy/rf/uhd_c_api.h +++ b/lib/src/phy/rf/uhd_c_api.h @@ -32,5 +32,6 @@ SRSLTE_API void rf_uhd_register_msg_handler_c(void (*new_handler)(const char*)); SRSLTE_API void uhd_tx_metadata_set_time_spec(uhd_tx_metadata_handle *md, time_t secs, double frac_secs); SRSLTE_API void uhd_tx_metadata_set_start(uhd_tx_metadata_handle *md, bool is_start_of_burst); +SRSLTE_API void uhd_tx_metadata_set_has_time_spec(uhd_tx_metadata_handle *md, bool has_time_spec); SRSLTE_API void uhd_tx_metadata_set_end(uhd_tx_metadata_handle *md, bool is_end_of_burst); SRSLTE_API void uhd_tx_metadata_add_time_spec(uhd_tx_metadata_handle *md, double frac_secs); diff --git a/lib/src/phy/ue/ue_sync.c b/lib/src/phy/ue/ue_sync.c index 2126950a6..3f5b131eb 100644 --- a/lib/src/phy/ue/ue_sync.c +++ b/lib/src/phy/ue/ue_sync.c @@ -513,7 +513,7 @@ static int track_peak_ok(srslte_ue_sync_t *q, uint32_t track_idx) { discard the offseted samples to align next frame */ if (q->next_rf_sample_offset > 0 && q->next_rf_sample_offset < MAX_TIME_OFFSET) { DEBUG("Positive time offset %d samples.\n", q->next_rf_sample_offset); - if (q->recv_callback(q->stream, dummy_offset_buffer, (uint32_t) q->next_rf_sample_offset, &q->last_timestamp) < 0) { + if (q->recv_callback(q->stream, dummy_offset_buffer, (uint32_t) q->next_rf_sample_offset, NULL) < 0) { fprintf(stderr, "Error receiving from USRP\n"); return SRSLTE_ERROR; } diff --git a/lib/src/radio/radio.cc b/lib/src/radio/radio.cc index 6cd2d9dd3..c0e828f71 100644 --- a/lib/src/radio/radio.cc +++ b/lib/src/radio/radio.cc @@ -120,11 +120,6 @@ void radio::set_tx_adv_neg(bool tx_adv_is_neg) { tx_adv_negative = tx_adv_is_neg; } -void radio::tx_offset(int offset_) -{ - offset = offset_; -} - bool radio::start_agc(bool tx_gain_same_rx) { if (srslte_rf_start_gain_thread(&rf_device, tx_gain_same_rx)) { @@ -185,6 +180,12 @@ bool radio::has_rssi() return srslte_rf_has_rssi(&rf_device); } +bool radio::is_first_of_burst() { + return is_start_of_burst; +} + +#define BLOCKING_TX true + bool radio::tx(void* buffer, uint32_t nof_samples, srslte_timestamp_t tx_time) { void *iq_samples[4] = {(void *) zeros, (void *) zeros, (void *) zeros, (void *) zeros}; @@ -203,7 +204,7 @@ bool radio::tx(void* buffer, uint32_t nof_samples, srslte_timestamp_t tx_time) save_trace(1, &tx_time_pad); srslte_rf_send_timed_multi(&rf_device, iq_samples, burst_preamble_samples, tx_time_pad.full_secs, tx_time_pad.frac_secs, true, true, false); is_start_of_burst = false; - } + } } // Save possible end of burst time @@ -212,9 +213,10 @@ bool radio::tx(void* buffer, uint32_t nof_samples, srslte_timestamp_t tx_time) save_trace(0, &tx_time); iq_samples[0] = buffer; - int ret = srslte_rf_send_timed_multi(&rf_device, (void**) iq_samples, nof_samples+offset, tx_time.full_secs, tx_time.frac_secs, true, is_start_of_burst, false); - offset = 0; - is_start_of_burst = false; + int ret = srslte_rf_send_timed_multi(&rf_device, (void**) iq_samples, nof_samples, + tx_time.full_secs, tx_time.frac_secs, + BLOCKING_TX, is_start_of_burst, false); + is_start_of_burst = false; if (ret > 0) { return true; } else { @@ -222,16 +224,6 @@ bool radio::tx(void* buffer, uint32_t nof_samples, srslte_timestamp_t tx_time) } } -uint32_t radio::get_tti_len() -{ - return sf_len; -} - -void radio::set_tti_len(uint32_t sf_len_) -{ - sf_len = sf_len_; -} - void radio::tx_end() { if (!is_start_of_burst) { diff --git a/srsue/hdr/mac/ul_harq.h b/srsue/hdr/mac/ul_harq.h index 52aef7bd7..4749971b6 100644 --- a/srsue/hdr/mac/ul_harq.h +++ b/srsue/hdr/mac/ul_harq.h @@ -368,6 +368,7 @@ private: current_tx_nb = 0; current_irv = 0; is_msg3 = is_msg3_; + Info("UL %d: New TX%s, RV=%d, TBS=%d, RNTI=%d\n", pid, is_msg3?" for Msg3":"", get_rv(), cur_grant.n_bytes[0], is_msg3?harq_entity->rntis->temp_rnti:cur_grant.rnti); diff --git a/srsue/hdr/phy/phch_common.h b/srsue/hdr/phy/phch_common.h index 851fc3581..aa64fe9ea 100644 --- a/srsue/hdr/phy/phch_common.h +++ b/srsue/hdr/phy/phch_common.h @@ -27,6 +27,9 @@ #ifndef UEPHYWORKERCOMMON_H #define UEPHYWORKERCOMMON_H +#define TX_MODE_CONTINUOUS 1 + + #include #include #include @@ -36,8 +39,6 @@ #include "srslte/common/log.h" #include "phy/phy_metrics.h" -//#define CONTINUOUS_TX - namespace srsue { diff --git a/srsue/hdr/phy/phch_recv.h b/srsue/hdr/phy/phch_recv.h index ac033f607..8c768f46b 100644 --- a/srsue/hdr/phy/phch_recv.h +++ b/srsue/hdr/phy/phch_recv.h @@ -67,7 +67,13 @@ public: void set_time_adv_sec(float time_adv_sec); void get_current_cell(srslte_cell_t *cell); - const static int MUTEX_X_WORKER = 4; + const static int MUTEX_X_WORKER = 4; + + // public variables needed by callback function + uint32_t current_sflen; + srslte::radio_multi *radio_h; + int next_offset; + private: @@ -97,7 +103,6 @@ private: bool running; - srslte::radio_multi *radio_h; mac_interface_phy *mac; rrc_interface_phy *rrc; srslte::log *log_h; @@ -133,6 +138,7 @@ private: enum { SRATE_NONE=0, SRATE_FIND, SRATE_CAMP } srate_mode; + float current_srate; srslte_cell_t cell; bool cell_is_set; diff --git a/srsue/hdr/phy/phch_worker.h b/srsue/hdr/phy/phch_worker.h index 307cea0f0..0811723e0 100644 --- a/srsue/hdr/phy/phch_worker.h +++ b/srsue/hdr/phy/phch_worker.h @@ -52,7 +52,7 @@ public: /* Functions used by main PHY thread */ cf_t* get_buffer(uint32_t antenna_idx); void set_tti(uint32_t tti, uint32_t tx_tti); - void set_tx_time(srslte_timestamp_t tx_time); + void set_tx_time(srslte_timestamp_t tx_time, uint32_t next_offset); void set_cfo(float cfo); void set_sample_offset(float sample_offset); @@ -123,7 +123,9 @@ private: bool pregen_enabled; uint32_t last_dl_pdcch_ncce; bool rnti_is_set; - + + uint32_t next_offset; + /* Objects for DL */ srslte_ue_dl_t ue_dl; uint32_t cfi; diff --git a/srsue/src/phy/phch_common.cc b/srsue/src/phy/phch_common.cc index 1eb0be420..6baf0b70e 100644 --- a/srsue/src/phy/phch_common.cc +++ b/srsue/src/phy/phch_common.cc @@ -34,8 +34,6 @@ #define Info(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->info_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) #define Debug(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->debug_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define TX_MODE_CONTINUOUS 0 - namespace srsue { cf_t zeros[50000]; diff --git a/srsue/src/phy/phch_recv.cc b/srsue/src/phy/phch_recv.cc index 630de4518..ba09f2d53 100644 --- a/srsue/src/phy/phch_recv.cc +++ b/srsue/src/phy/phch_recv.cc @@ -39,15 +39,16 @@ 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; +int radio_recv_wrapper_cs(void *obj, cf_t *data[SRSLTE_MAX_PORTS], uint32_t nsamples, srslte_timestamp_t *rx_time) { + phch_recv *h = (phch_recv*) obj; + srslte::radio_multi *radio_h = h->radio_h; if (radio_h->rx_now(data, nsamples, rx_time)) { - int offset = nsamples - radio_h->get_tti_len(); + int offset = nsamples - h->current_sflen; if (abs(offset) < 10 && offset != 0) { - radio_h->tx_offset(offset); + h->next_offset = offset; } else if (nsamples < 10) { - radio_h->tx_offset(nsamples); + h->next_offset = nsamples; } return nsamples; } else { @@ -87,7 +88,7 @@ void phch_recv:: init(srslte::radio_multi *_radio_handler, mac_interface_phy *_ if (srslte_ue_cellsearch_init_multi(&cs, 5, radio_recv_wrapper_cs, nof_rx_antennas, - radio_h)) { + this)) { Error("SYNC: Initiating UE cell search\n"); return; } @@ -111,12 +112,12 @@ void phch_recv:: init(srslte::radio_multi *_radio_handler, mac_interface_phy *_ return; } - if (srslte_ue_sync_init_multi(&ue_sync, SRSLTE_MAX_PRB, false, radio_recv_wrapper_cs, nof_rx_antennas, radio_h)) { + if (srslte_ue_sync_init_multi(&ue_sync, SRSLTE_MAX_PRB, false, radio_recv_wrapper_cs, nof_rx_antennas, this)) { Error("SYNC: Initiating ue_sync\n"); return; } - if (srslte_ue_mib_sync_init_multi(&ue_mib_sync, radio_recv_wrapper_cs, nof_rx_antennas, radio_h)) { + if (srslte_ue_mib_sync_init_multi(&ue_mib_sync, radio_recv_wrapper_cs, nof_rx_antennas, this)) { Error("SYNC: Initiating UE MIB synchronization\n"); return; } @@ -154,6 +155,7 @@ void phch_recv::reset() { running = true; phy_state = IDLE; time_adv_sec = 0; + next_offset = 0; cell_is_set = false; sync_sfn_cnt = 0; srate_mode = SRATE_NONE; @@ -185,7 +187,12 @@ void phch_recv::set_agc_enable(bool enable) { } void phch_recv::set_time_adv_sec(float _time_adv_sec) { - time_adv_sec = _time_adv_sec; + if (TX_MODE_CONTINUOUS && !radio_h->is_first_of_burst()) { + int nsamples = ceil(current_srate*_time_adv_sec); + next_offset = -nsamples; + } else { + time_adv_sec = _time_adv_sec; + } } void phch_recv::set_ue_sync_opts(srslte_ue_sync_t *q) { @@ -241,7 +248,6 @@ bool phch_recv::set_cell() { 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); } @@ -578,18 +584,19 @@ bool phch_recv::set_frequency() void phch_recv::set_sampling_rate() { - float srate = (float) srslte_sampling_freq_hz(cell.nof_prb); - if (srate != -1) { - Info("SYNC: Setting sampling rate %.2f MHz\n", srate/1000000); + current_srate = (float) srslte_sampling_freq_hz(cell.nof_prb); + current_sflen = SRSLTE_SF_LEN_PRB(cell.nof_prb); + if (current_srate != -1) { + Info("SYNC: Setting sampling rate %.2f MHz\n", current_srate/1000000); - if (30720 % ((int) srate / 1000) == 0) { + if (30720 % ((int) current_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); + radio_h->set_rx_srate(current_srate); + radio_h->set_tx_srate(current_srate); } else { Error("Error setting sampling rate for cell with %d PRBs\n", cell.nof_prb); } @@ -702,7 +709,8 @@ void phch_recv::run_thread() { 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); + worker->set_tx_time(tx_time, next_offset); + next_offset = 0; 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); diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index 8e53d9ca0..3672c155d 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -294,7 +294,7 @@ void phch_worker::work_imp() } // Decode PHICH - bool ul_ack; + bool ul_ack = false; bool ul_ack_available = decode_phich(&ul_ack); /***** Uplink Processing + Transmission *******/ @@ -347,9 +347,13 @@ void phch_worker::work_imp() } tr_log_end(); - - phy->worker_end(tx_tti, signal_ready, signal_buffer[0], SRSLTE_SF_LEN_PRB(cell.nof_prb), tx_time); - + + if (next_offset > 0) { + phy->worker_end(tx_tti, signal_ready, signal_buffer[0], SRSLTE_SF_LEN_PRB(cell.nof_prb)+next_offset, tx_time); + } else { + phy->worker_end(tx_tti, signal_ready, &signal_buffer[0][-next_offset], SRSLTE_SF_LEN_PRB(cell.nof_prb)+next_offset, tx_time); + } + if (!dl_action.generate_ack_callback) { if (dl_mac_grant.rnti_type == SRSLTE_RNTI_PCH && dl_action.decode_enabled[0]) { phy->mac->pch_decoded_ok(dl_mac_grant.n_bytes[0]); @@ -867,8 +871,9 @@ bool phch_worker::srs_is_ready_to_send() { return false; } -void phch_worker::set_tx_time(srslte_timestamp_t _tx_time) +void phch_worker::set_tx_time(srslte_timestamp_t _tx_time, uint32_t next_offset) { + this->next_offset = next_offset; memcpy(&tx_time, &_tx_time, sizeof(srslte_timestamp_t)); } @@ -954,8 +959,8 @@ void phch_worker::encode_pucch() float tx_power = srslte_ue_ul_pucch_power(&ue_ul, phy->pathloss, ue_ul.last_pucch_format, uci_data.uci_cqi_len, uci_data.uci_ack_len); float gain = set_power(tx_power); - Info("PUCCH: power=%.2f dBm, tti_tx=%d, n_cce=%3d, n_pucch=%d, n_prb=%d, ack=%s%s, ri=%s, pmi=%s%s, sr=%s, cfo=%.1f Hz%s\n", - tx_power, (tti+4)%10240, + Info("PUCCH: tti_tx=%d, n_cce=%3d, n_pucch=%d, n_prb=%d, ack=%s%s, ri=%s, pmi=%s%s, sr=%s, cfo=%.1f Hz%s\n", + (tti+4)%10240, last_dl_pdcch_ncce, ue_ul.pucch.last_n_pucch, ue_ul.pucch.last_n_prb, uci_data.uci_ack_len>0?(uci_data.uci_ack?"1":"0"):"no", uci_data.uci_ack_len>1?(uci_data.uci_ack_2?"1":"0"):"",