From 11a2d2cc4ad7619f27683dc658291cb347eebaf3 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Fri, 17 Apr 2020 21:26:32 +0200 Subject: [PATCH] Fix and tidy up time offset in srsue --- lib/include/srslte/radio/radio.h | 5 ++- lib/src/radio/radio.cc | 38 +++++++++++++---- srsue/hdr/phy/ta_control.h | 73 +++----------------------------- srsue/src/phy/phy_common.cc | 3 ++ srsue/src/phy/sf_worker.cc | 15 +------ srsue/src/phy/sync.cc | 9 +--- 6 files changed, 44 insertions(+), 99 deletions(-) diff --git a/lib/include/srslte/radio/radio.h b/lib/include/srslte/radio/radio.h index b47e7bdb0..52754da46 100644 --- a/lib/include/srslte/radio/radio.h +++ b/lib/include/srslte/radio/radio.h @@ -334,7 +334,10 @@ private: channel_mapping rx_channel_mapping = {}, tx_channel_mapping = {}; - bool map_channels(channel_mapping& map, const rf_buffer_interface& buffer, void* radio_buffers[SRSLTE_MAX_CHANNELS]); + bool map_channels(channel_mapping& map, + uint32_t sample_offset, + const rf_buffer_interface& buffer, + void* radio_buffers[SRSLTE_MAX_CHANNELS]); bool start_agc(bool tx_gain_same_rx = false); void set_tx_adv(int nsamples); void set_tx_adv_neg(bool tx_adv_is_neg); diff --git a/lib/src/radio/radio.cc b/lib/src/radio/radio.cc index 681e9de78..2e05059cd 100644 --- a/lib/src/radio/radio.cc +++ b/lib/src/radio/radio.cc @@ -222,7 +222,7 @@ bool radio::rx_now(rf_buffer_interface& buffer, const uint32_t& nof_samples, srs double* frac_secs = rxd_time ? &rxd_time->frac_secs : NULL; void* radio_buffers[SRSLTE_MAX_CHANNELS] = {}; - if (!map_channels(rx_channel_mapping, buffer, radio_buffers)) { + if (!map_channels(rx_channel_mapping, 0, buffer, radio_buffers)) { log_h->error("Mapping logical channels to physical channels for transmission\n"); return false; } @@ -260,8 +260,11 @@ bool radio::has_rssi() return srslte_rf_has_rssi(&rf_device); } -bool radio::tx(rf_buffer_interface& buffer, const uint32_t& nof_samples, const srslte_timestamp_t& tx_time_) +bool radio::tx(rf_buffer_interface& buffer, const uint32_t& nof_samples_, const srslte_timestamp_t& tx_time_) { + uint32_t nof_samples = nof_samples_; + uint32_t sample_offset = 0; + if (!is_initialized) { return false; } @@ -272,12 +275,32 @@ bool radio::tx(rf_buffer_interface& buffer, const uint32_t& nof_samples, const s srslte_timestamp_add(&tx_time, 0, tx_adv_sec); } + // Calculate Tx gap if it is not start of the burst + if (not is_start_of_burst) { + srslte_timestamp_t tx_gap = end_of_burst_time; + srslte_timestamp_sub(&tx_gap, tx_time.full_secs, tx_time.frac_secs); + int32_t past_nsamples = (int32_t)round(cur_tx_srate * srslte_timestamp_real(&tx_gap)); + + // Negative gap, trimming first samples by setting a sample offset. Otherwise, ignore + if (past_nsamples > 0) { + // If the gap is larger than the amount of samples to transmit, return without doing anything else + if ((int32_t)nof_samples < past_nsamples) { + return true; + } + + // Update transmission parameters + tx_time = end_of_burst_time; + nof_samples -= past_nsamples; + sample_offset = (uint32_t)past_nsamples; + } + } + // Save possible end of burst time srslte_timestamp_copy(&end_of_burst_time, &tx_time); srslte_timestamp_add(&end_of_burst_time, 0, (double)nof_samples / cur_tx_srate); void* radio_buffers[SRSLTE_MAX_CHANNELS] = {}; - if (!map_channels(rx_channel_mapping, buffer, radio_buffers)) { + if (!map_channels(rx_channel_mapping, sample_offset, buffer, radio_buffers)) { log_h->error("Mapping logical channels to physical channels for transmission\n"); return false; } @@ -285,11 +308,7 @@ bool radio::tx(rf_buffer_interface& buffer, const uint32_t& nof_samples, const s int ret = srslte_rf_send_timed_multi( &rf_device, radio_buffers, nof_samples, tx_time.full_secs, tx_time.frac_secs, true, is_start_of_burst, false); is_start_of_burst = false; - if (ret > 0) { - return true; - } else { - return false; - } + return ret > SRSLTE_SUCCESS; } void radio::tx_end() @@ -616,6 +635,7 @@ void radio::rf_msg_callback(void* arg, srslte_rf_error_t error) } bool radio::map_channels(channel_mapping& map, + uint32_t sample_offset, const rf_buffer_interface& buffer, void* radio_buffers[SRSLTE_MAX_CHANNELS]) { @@ -630,7 +650,7 @@ bool radio::map_channels(channel_mapping& map, uint32_t physical_idx = map.get_carrier_idx(i); for (uint32_t j = 0; j < nof_antennas; j++) { if (physical_idx * nof_antennas + j < SRSLTE_MAX_CHANNELS) { - radio_buffers[physical_idx * nof_antennas + j] = buffer.get(i, j, nof_antennas); + radio_buffers[physical_idx * nof_antennas + j] = buffer.get(i, j, nof_antennas) + sample_offset; } else { return false; } diff --git a/srsue/hdr/phy/ta_control.h b/srsue/hdr/phy/ta_control.h index 892d703d4..08a6f6830 100644 --- a/srsue/hdr/phy/ta_control.h +++ b/srsue/hdr/phy/ta_control.h @@ -35,9 +35,6 @@ private: mutable std::mutex mutex; uint32_t next_base_nta = 0; float next_base_sec = 0.0f; - float current_base_sec = 0.0f; - float prev_base_sec = 0.0f; - int32_t pending_nsamples = 0; public: /** @@ -62,9 +59,6 @@ public: // Update base in nta next_base_nta = static_cast(roundf(next_base_sec / SRSLTE_LTE_TS)); - // Resets pending samples - pending_nsamples = 0; - // Log information information if available if (log_h) { log_h->info("PHY: Set TA base: n_ta: %d, ta_usec: %.1f\n", next_base_nta, next_base_sec * 1e6f); @@ -138,43 +132,17 @@ public: } } - /** - * Increments/Decrements the number pending samples for next transmission - * - * @param nsamples is the number of samples - */ - void set_pending_nsamples(int32_t nsamples) - { - std::lock_guard lock(mutex); - - // Increment number of pending samples - pending_nsamples += nsamples; - } - - /** - * Get the previous time alignment in seconds - * - * @return Time alignment in seconds - */ - float get_previous_sec() const - { - std::lock_guard lock(mutex); - - // Returns the previous base - return prev_base_sec; - } - /** * Get the current time alignment in seconds * * @return Time alignment in seconds */ - float get_current_sec() const + float get_sec() const { std::lock_guard lock(mutex); // Returns the current base - return current_base_sec; + return next_base_sec; } /** @@ -182,12 +150,12 @@ public: * * @return Time alignment in microseconds */ - float get_current_usec() const + float get_usec() const { std::lock_guard lock(mutex); // Returns the current base - return current_base_sec * 1e6f; + return next_base_sec * 1e6f; } /** @@ -195,41 +163,12 @@ public: * * @return Distance based on the current time base */ - float get_current_km() const + float get_km() const { std::lock_guard lock(mutex); // Returns the current base, one direction distance - return current_base_sec * (3.6f * 3e8f / 2.0f); - } - - /** - * Get the total number of pending samples to transmit, considering the time difference between the next base and the - * current base. - * - * Attention: this method changes the internal state of the class. - * - * @return the total number of pending samples considering the sampling rate - */ - int32_t get_pending_nsamples(uint32_t sampling_rate_hz) - { - std::lock_guard lock(mutex); - - // Convert sampling rate to float - float srate = static_cast(sampling_rate_hz); - - // Calculate number of samples - int32_t nsamples = static_cast(roundf(srate * (current_base_sec - next_base_sec))); - - // Update current base - prev_base_sec = current_base_sec; - current_base_sec = next_base_sec; - - // Reset pending samples - pending_nsamples = 0; - - // Return number of samples - return nsamples; + return next_base_sec * (3.6f * 3e8f / 2.0f); } }; diff --git a/srsue/src/phy/phy_common.cc b/srsue/src/phy/phy_common.cc index 09300f2e3..9122c71f4 100644 --- a/srsue/src/phy/phy_common.cc +++ b/srsue/src/phy/phy_common.cc @@ -532,6 +532,9 @@ void phy_common::worker_end(void* tx_sem_id, // Wait for the green light to transmit in the current TTI semaphore.wait(tx_sem_id); + // Add Time Alignment + srslte_timestamp_sub(&tx_time, 0, ta.get_sec()); + // For each radio, transmit if (tx_enable && !srslte_timestamp_iszero(&tx_time)) { diff --git a/srsue/src/phy/sf_worker.cc b/srsue/src/phy/sf_worker.cc index 1d17dfafd..69f326005 100644 --- a/srsue/src/phy/sf_worker.cc +++ b/srsue/src/phy/sf_worker.cc @@ -206,7 +206,6 @@ void sf_worker::work_imp() bool rx_signal_ok = false; bool tx_signal_ready = false; uint32_t nof_samples = SRSLTE_SF_LEN_PRB(cell.nof_prb); - int32_t next_offset = 0; { std::lock_guard lock(mutex); @@ -231,9 +230,6 @@ void sf_worker::work_imp() } } - // Load TA - next_offset = phy->ta.get_pending_nsamples(nof_samples * 1000U); - /***** Uplink Generation + Transmission *******/ /* If TTI+4 is an uplink subframe (TODO: Support short PRACH and SRS in UpPts special subframes) */ @@ -250,12 +246,7 @@ void sf_worker::work_imp() tx_signal_ready |= cc_workers[carrier_idx]->work_ul(&uci_data); // Set signal pointer based on offset - cf_t* b = cc_workers[carrier_idx]->get_tx_buffer(0); - if (next_offset > 0) { - tx_signal_ptr.set(carrier_idx, 0, phy->args->nof_rx_ant, b); - } else { - tx_signal_ptr.set(carrier_idx, 0, phy->args->nof_rx_ant, &b[-next_offset]); - } + tx_signal_ptr.set((uint32_t)carrier_idx, 0, phy->args->nof_rx_ant, cc_workers[carrier_idx]->get_tx_buffer(0)); } } } @@ -263,13 +254,9 @@ void sf_worker::work_imp() // Set PRACH buffer signal pointer if (prach_ptr) { - srslte_timestamp_sub(&tx_time, 0, phy->ta.get_current_sec()); tx_signal_ready = true; tx_signal_ptr.set(0, prach_ptr); prach_ptr = nullptr; - } else { - srslte_timestamp_sub(&tx_time, 0, phy->ta.get_previous_sec()); - nof_samples += next_offset; } // Call worker_end to transmit the signal diff --git a/srsue/src/phy/sync.cc b/srsue/src/phy/sync.cc index 91bdc6ec5..e5a5eeba5 100644 --- a/srsue/src/phy/sync.cc +++ b/srsue/src/phy/sync.cc @@ -473,7 +473,7 @@ void sync::run_thread() metrics.sfo = srslte_ue_sync_get_sfo(&ue_sync); metrics.cfo = srslte_ue_sync_get_cfo(&ue_sync); - metrics.ta_us = worker_com->ta.get_current_usec(); + metrics.ta_us = worker_com->ta.get_usec(); for (uint32_t i = 0; i < worker_com->args->nof_carriers; i++) { worker_com->set_sync_metrics(i, metrics); } @@ -862,13 +862,6 @@ int sync::radio_recv_fnc(srslte::rf_buffer_t& data, uint32_t nsamples, srslte_ti } } - int offset = nsamples - current_sflen; - if (abs(offset) < 10 && offset != 0) { - worker_com->ta.set_pending_nsamples(offset); - } else if (nsamples < 10) { - worker_com->ta.set_pending_nsamples(nsamples); - } - log_h->debug("SYNC: received %d samples from radio\n", nsamples); return nsamples;