Integrates number of samples in radio buffer

Fix minor issue

Radio: Fix minor bug and add unit test
This commit is contained in:
Xavier Arteaga 2020-05-19 10:19:36 +02:00 committed by Xavier Arteaga
parent de230826b9
commit f04cf2090a
21 changed files with 150 additions and 146 deletions

View File

@ -42,7 +42,7 @@ static inline std::string string_remove_char(const std::string& input, char c)
while (p1 != std::string::npos) {
ret.erase(p1);
p1 = ret.find(' ');
p1 = ret.find(c);
}
return ret;

View File

@ -56,6 +56,8 @@ public:
virtual void** to_void() = 0;
virtual cf_t** to_cf_t() = 0;
virtual uint32_t size() = 0;
virtual void set_nof_samples(uint32_t n) = 0;
virtual uint32_t get_nof_samples() const = 0;
};
/**
@ -119,22 +121,20 @@ public:
* the buffer object.
*
* @param buffer Is the object that contains the pointers to all RF channels
* @param nof_samples Number of samples to transmit on all carriers and antennas
* @param tx_time Time to transmit all signals
* @return it returns true if the transmission was successful, otherwise it returns false
*/
virtual bool tx(rf_buffer_interface& buffer, const uint32_t& nof_samples, const rf_timestamp_interface& tx_time) = 0;
virtual bool tx(rf_buffer_interface& buffer, const rf_timestamp_interface& tx_time) = 0;
/**
* Indicates the radio to receive from all antennas and carriers synchronously and store the samples
* in the buffer object
*
* @param buffer Is the object where the samples will be stored
* @param nof_samples Number of samples to receive from all carriers and antennas
* @param tx_time Time at which the samples were received. Note the time is the same for all carriers
* @return
*/
virtual bool rx_now(rf_buffer_interface& buffer, const uint32_t& nof_samples, rf_timestamp_interface& rxd_time) = 0;
virtual bool rx_now(rf_buffer_interface& buffer, rf_timestamp_interface& rxd_time) = 0;
/**
* Sets the TX frequency for all antennas in the provided carrier index

View File

@ -60,8 +60,8 @@ public:
// trx functions
void tx_end() override;
bool tx(rf_buffer_interface& buffer, const uint32_t& nof_samples, const rf_timestamp_interface& tx_time) override;
bool rx_now(rf_buffer_interface& buffer, const uint32_t& nof_samples, rf_timestamp_interface& rxd_time) override;
bool tx(rf_buffer_interface& buffer, const rf_timestamp_interface& tx_time) override;
bool rx_now(rf_buffer_interface& buffer, rf_timestamp_interface& rxd_time) override;
// setter
void set_tx_freq(const uint32_t& carrier_idx, const double& freq) override;
@ -165,7 +165,6 @@ private:
*/
bool tx_dev(const uint32_t& device_idx,
rf_buffer_interface& buffer,
const uint32_t& nof_samples_,
const srslte_timestamp_t& tx_time_);
/**
@ -174,13 +173,11 @@ private:
*
* @param device_idx Device index
* @param buffer Common receive buffers
* @param nof_samples Number of samples to receive
* @param rxd_time Points at the receive time (write only)
* @return it returns true if the reception was successful, otherwise it returns false
*/
bool rx_dev(const uint32_t& device_idx,
const rf_buffer_interface& buffer,
const uint32_t& nof_samples,
srslte_timestamp_t* rxd_time);
/**

View File

@ -57,17 +57,22 @@ public:
* contain up to SRSLTE_MAX_CHANNELS pointers
* @param data Flat array to use as initializer for the internal buffer pointers
*/
explicit rf_buffer_t(cf_t* data[SRSLTE_MAX_CHANNELS])
explicit rf_buffer_t(cf_t* data[SRSLTE_MAX_CHANNELS], uint32_t nof_samples_)
{
for (uint32_t i = 0; i < SRSLTE_MAX_CHANNELS; i++) {
sample_buffer[i] = data[i];
}
nof_samples = nof_samples_;
}
/**
* Creates an object from a single array pointer. The rest of the channel pointers will be left to NULL
* @param data Flat array to use as initializer for the internal buffer pointers
*/
explicit rf_buffer_t(cf_t* data) { sample_buffer[0] = data; }
explicit rf_buffer_t(cf_t* data, uint32_t nof_samples_)
{
sample_buffer[0] = data;
nof_samples = nof_samples_;
}
/**
* Default constructor leaves the internal pointers to NULL
*/
@ -119,11 +124,14 @@ public:
void** to_void() override { return (void**)sample_buffer.data(); }
cf_t** to_cf_t() override { return sample_buffer.data(); }
uint32_t size() override { return nof_subframes * SRSLTE_SF_LEN_MAX; }
void set_nof_samples(uint32_t n) override { nof_samples = n; }
uint32_t get_nof_samples() const override { return nof_samples; }
private:
std::array<cf_t*, SRSLTE_MAX_CHANNELS> sample_buffer = {};
bool allocated = false;
uint32_t nof_subframes = 0;
uint32_t nof_samples = 0;
void free_all()
{
for (uint32_t i = 0; i < SRSLTE_MAX_CHANNELS; i++) {

View File

@ -88,7 +88,7 @@ int radio::init(const rf_args_t& args, phy_interface_radio* phy_)
// Split multiple RF channels using `;` delimiter
std::vector<std::string> device_args_list;
string_parse_list(args.device_args, ',', device_args_list);
string_parse_list(args.device_args, ';', device_args_list);
// Add auto if list is empty
if (device_args_list.empty()) {
@ -211,7 +211,7 @@ bool radio::start_agc(bool tx_gain_same_rx)
return true;
}
bool radio::rx_now(rf_buffer_interface& buffer, const uint32_t& nof_samples, rf_timestamp_interface& rxd_time)
bool radio::rx_now(rf_buffer_interface& buffer, rf_timestamp_interface& rxd_time)
{
bool ret = true;
@ -223,7 +223,7 @@ bool radio::rx_now(rf_buffer_interface& buffer, const uint32_t& nof_samples, rf_
}
for (uint32_t device_idx = 0; device_idx < (uint32_t)rf_devices.size(); device_idx++) {
ret &= rx_dev(device_idx, buffer, nof_samples, rxd_time.get_ptr(device_idx));
ret &= rx_dev(device_idx, buffer, rxd_time.get_ptr(device_idx));
}
return ret;
@ -231,7 +231,6 @@ bool radio::rx_now(rf_buffer_interface& buffer, const uint32_t& nof_samples, rf_
bool radio::rx_dev(const uint32_t& device_idx,
const rf_buffer_interface& buffer,
const uint32_t& nof_samples,
srslte_timestamp_t* rxd_time)
{
if (!is_initialized) {
@ -247,17 +246,17 @@ bool radio::rx_dev(const uint32_t& device_idx,
return false;
}
int ret =
srslte_rf_recv_with_time_multi(&rf_devices[device_idx], radio_buffers, nof_samples, true, full_secs, frac_secs);
int ret = srslte_rf_recv_with_time_multi(
&rf_devices[device_idx], radio_buffers, buffer.get_nof_samples(), true, full_secs, frac_secs);
return ret > 0;
}
bool radio::tx(rf_buffer_interface& buffer, const uint32_t& nof_samples, const rf_timestamp_interface& tx_time)
bool radio::tx(rf_buffer_interface& buffer, const rf_timestamp_interface& tx_time)
{
bool ret = true;
for (uint32_t device_idx = 0; device_idx < (uint32_t)rf_devices.size(); device_idx++) {
ret &= tx_dev(device_idx, buffer, nof_samples, tx_time.get(device_idx));
ret &= tx_dev(device_idx, buffer, tx_time.get(device_idx));
}
is_start_of_burst = false;
@ -303,10 +302,9 @@ bool radio::open_dev(const uint32_t& device_idx, const std::string& device_name,
bool radio::tx_dev(const uint32_t& device_idx,
rf_buffer_interface& buffer,
const uint32_t& nof_samples_,
const srslte_timestamp_t& tx_time_)
{
uint32_t nof_samples = nof_samples_;
uint32_t nof_samples = buffer.get_nof_samples();
uint32_t sample_offset = 0;
srslte_rf_t* rf_device = &rf_devices[device_idx];

View File

@ -25,6 +25,11 @@ if(RF_FOUND)
include_directories(${SRSGUI_INCLUDE_DIRS})
target_link_libraries(benchmark_radio ${SRSGUI_LIBRARIES})
endif(SRSGUI_FOUND)
if (ZEROMQ_FOUND)
add_test(benchmark_radio_multi_rf benchmark_radio -d zmq -a
tx_port=tcp://*:2000,rx_port=tcp://localhost:2000\;tx_port=tcp://*:2001,rx_port=tcp://localhost:2001\;tx_port=tcp://*:2002,rx_port=tcp://localhost:2002\;tx_port=tcp://*:2003,rx_port=tcp://localhost:2003\;
-p 4)
endif (ZEROMQ_FOUND)
endif(RF_FOUND)

View File

@ -39,7 +39,7 @@ using namespace srslte;
#define SRSLTE_MAX_RADIOS 3
static char radios_args[SRSLTE_MAX_RADIOS][64] = {"auto", "auto", "auto"};
static std::array<std::string, SRSLTE_MAX_RADIOS> radios_args = {"auto", "auto", "auto"};
static char radio_device[64];
static log_filter log_h;
@ -77,9 +77,9 @@ void usage(char* prog)
printf("Usage: %s [foabcderpstvhmFxw]\n", prog);
printf("\t-f Carrier frequency in Hz [Default %f]\n", freq);
printf("\t-g RF gain [Default AGC]\n");
printf("\t-a Arguments for first radio [Default %s]\n", radios_args[0]);
printf("\t-b Arguments for second radio [Default %s]\n", radios_args[1]);
printf("\t-c Arguments for third radio [Default %s]\n", radios_args[2]);
printf("\t-a Arguments for first radio [Default %s]\n", radios_args[0].c_str());
printf("\t-b Arguments for second radio [Default %s]\n", radios_args[1].c_str());
printf("\t-c Arguments for third radio [Default %s]\n", radios_args[2].c_str());
printf("\t-d Radio device [Default %s]\n", radio_device);
printf("\t-r number of radios 1-%d [Default %d]\n", SRSLTE_MAX_RADIOS, nof_radios);
printf("\t-p number of ports 1-%d [Default %d]\n", SRSLTE_MAX_PORTS, nof_ports);
@ -111,16 +111,13 @@ void parse_args(int argc, char** argv)
file_pattern = argv[optind];
break;
case 'a':
strncpy(radios_args[0], argv[optind], 63);
radios_args[0][63] = '\0';
radios_args[0] = std::string(argv[optind]);
break;
case 'b':
strncpy(radios_args[1], argv[optind], 63);
radios_args[1][63] = '\0';
radios_args[1] = std::string(argv[optind]);
break;
case 'c':
strncpy(radios_args[2], argv[optind], 63);
radios_args[2][63] = '\0';
radios_args[2] = std::string(argv[optind]);
break;
case 'd':
strncpy(radio_device, argv[optind], 63);
@ -409,7 +406,8 @@ int main(int argc, char** argv)
// receive each radio
for (uint32_t r = 0; r < nof_radios; r++) {
radio_h[r]->rx_now(rf_buffers[r], frame_size, ts_rx[r]);
rf_buffers[r].set_nof_samples(frame_size);
radio_h[r]->rx_now(rf_buffers[r], ts_rx[r]);
}
// run agc
@ -424,7 +422,8 @@ int main(int argc, char** argv)
for (uint32_t r = 0; r < nof_radios; r++) {
ts_tx.copy(ts_rx[r]);
ts_tx.add(0.004);
radio_h[r]->tx(rf_buffers[r], frame_size, ts_tx);
rf_buffers[r].set_nof_samples(frame_size);
radio_h[r]->tx(rf_buffers[r], ts_tx);
}
}

View File

@ -60,10 +60,9 @@ public:
*
* @param tx_sem_id Semaphore identifier, the worker thread pointer is used
* @param buffer baseband IQ sample buffer
* @param nof_samples number of samples to transmit
* @param tx_time timestamp to transmit samples
*/
void worker_end(void* tx_sem_id, srslte::rf_buffer_t& buffer, uint32_t nof_samples, srslte::rf_timestamp_t& tx_time);
void worker_end(void* tx_sem_id, srslte::rf_buffer_t& buffer, srslte::rf_timestamp_t& tx_time);
// Common objects
phy_args_t params = {};

View File

@ -126,7 +126,6 @@ void phy_common::set_ul_grants(uint32_t tti, const stack_interface_phy_lte::ul_s
*/
void phy_common::worker_end(void* tx_sem_id,
srslte::rf_buffer_t& buffer,
uint32_t nof_samples,
srslte::rf_timestamp_t& tx_time)
{
// Wait for the green light to transmit in the current TTI
@ -134,11 +133,11 @@ void phy_common::worker_end(void* tx_sem_id,
// Run DL channel emulator if created
if (dl_channel) {
dl_channel->run(buffer.to_cf_t(), buffer.to_cf_t(), nof_samples, tx_time.get(0));
dl_channel->run(buffer.to_cf_t(), buffer.to_cf_t(), buffer.get_nof_samples(), tx_time.get(0));
}
// Always transmit on single radio
radio->tx(buffer, nof_samples, tx_time);
radio->tx(buffer, tx_time);
// Trigger MAC clock
stack->tti_clock();

View File

@ -179,7 +179,7 @@ void sf_worker::work_imp()
}
if (!running) {
phy->worker_end(this, tx_buffer, 0, tx_time);
phy->worker_end(this, tx_buffer, tx_time);
return;
}
@ -212,14 +212,14 @@ void sf_worker::work_imp()
if (sf_type == SRSLTE_SF_NORM) {
if (stack->get_dl_sched(tti_tx_dl, dl_grants) < 0) {
Error("Getting DL scheduling from MAC\n");
phy->worker_end(this, tx_buffer, 0, tx_time);
phy->worker_end(this, tx_buffer, tx_time);
return;
}
} else {
dl_grants[0].cfi = mbsfn_cfg.non_mbsfn_region_length;
if (stack->get_mch_sched(tti_tx_dl, mbsfn_cfg.is_mcch, dl_grants)) {
Error("Getting MCH packets from MAC\n");
phy->worker_end(this, tx_buffer, 0, tx_time);
phy->worker_end(this, tx_buffer, tx_time);
return;
}
}
@ -231,7 +231,7 @@ void sf_worker::work_imp()
// Get UL scheduling for the TX TTI from MAC
if (stack->get_ul_sched(tti_tx_ul, ul_grants_tx) < 0) {
Error("Getting UL scheduling from MAC\n");
phy->worker_end(this, tx_buffer, 0, tx_time);
phy->worker_end(this, tx_buffer, tx_time);
return;
}
@ -254,7 +254,8 @@ void sf_worker::work_imp()
phy->set_ul_grants(t_rx, ul_grants);
Debug("Sending to radio\n");
phy->worker_end(this, tx_buffer, SRSLTE_SF_LEN_PRB(phy->get_nof_prb(0)), tx_time);
tx_buffer.set_nof_samples(SRSLTE_SF_LEN_PRB(phy->get_nof_prb(0)));
phy->worker_end(this, tx_buffer, tx_time);
#ifdef DEBUG_WRITE_FILE
fwrite(signal_buffer_tx, SRSLTE_SF_LEN_PRB(phy->cell.nof_prb) * sizeof(cf_t), 1, f);

View File

@ -133,7 +133,8 @@ void txrx::run_thread()
}
}
radio_h->rx_now(buffer, sf_len, timestamp);
buffer.set_nof_samples(sf_len);
radio_h->rx_now(buffer, timestamp);
if (ul_channel) {
ul_channel->run(buffer.to_cf_t(), buffer.to_cf_t(), sf_len, timestamp.get(0));

View File

@ -188,15 +188,14 @@ public:
}
bool tx(srslte::rf_buffer_interface& buffer,
const uint32_t& nof_samples,
const srslte::rf_timestamp_interface& tx_time) override
{
int err = SRSLTE_SUCCESS;
// Get number of bytes to write
uint32_t nbytes = static_cast<uint32_t>(sizeof(cf_t)) * nof_samples;
uint32_t nbytes = static_cast<uint32_t>(sizeof(cf_t)) * buffer.get_nof_samples();
log_h.debug("tx %d\n", nof_samples);
log_h.debug("tx %d\n", buffer.get_nof_samples());
// Write ring buffer
for (uint32_t i = 0; i < ringbuffers_tx.size() and err >= SRSLTE_SUCCESS; i++) {
@ -211,15 +210,14 @@ public:
}
void tx_end() override {}
bool rx_now(srslte::rf_buffer_interface& buffer,
const uint32_t& nof_samples,
srslte::rf_timestamp_interface& rxd_time) override
{
int err = SRSLTE_SUCCESS;
log_h.info("rx_now %d\n", nof_samples);
log_h.info("rx_now %d\n", buffer.get_nof_samples());
// Get number of bytes to read
uint32_t nbytes = static_cast<uint32_t>(sizeof(cf_t)) * nof_samples;
uint32_t nbytes = static_cast<uint32_t>(sizeof(cf_t)) * buffer.get_nof_samples();
// Write ring buffer
for (uint32_t i = 0; i < ringbuffers_rx.size() and err >= SRSLTE_SUCCESS; i++) {
@ -233,7 +231,7 @@ public:
// Copy new timestamp
if (std::isnormal(rx_srate)) {
ts_rx.add(static_cast<double>(nof_samples) / rx_srate);
ts_rx.add(static_cast<double>(buffer.get_nof_samples()) / rx_srate);
}
// Notify Rx

View File

@ -141,7 +141,6 @@ public:
void worker_end(void* h,
bool tx_enable,
srslte::rf_buffer_t& buffer,
uint32_t nof_samples,
srslte::rf_timestamp_t& tx_time);
void set_cell(const srslte_cell_t& c);

View File

@ -31,7 +31,7 @@ namespace srsue {
class search_callback
{
public:
virtual int radio_recv_fnc(srslte::rf_buffer_t&, uint32_t nsamples, srslte_timestamp_t* rx_time) = 0;
virtual int radio_recv_fnc(srslte::rf_buffer_t&, srslte_timestamp_t* rx_time) = 0;
virtual void set_ue_sync_opts(srslte_ue_sync_t* q, float cfo) = 0;
virtual srslte::radio_interface_phy* get_radio() = 0;
virtual void set_rx_gain(float gain) = 0;

View File

@ -89,7 +89,7 @@ public:
// Other functions
void set_rx_gain(float gain) override;
int radio_recv_fnc(srslte::rf_buffer_t&, uint32_t nsamples, srslte_timestamp_t* rx_time) override;
int radio_recv_fnc(srslte::rf_buffer_t&, srslte_timestamp_t* rx_time) override;
srslte::radio_interface_phy* get_radio() override { return radio_h; }

View File

@ -524,7 +524,6 @@ bool phy_common::get_dl_pending_ack(srslte_ul_sf_cfg_t* sf, uint32_t cc_idx, srs
void phy_common::worker_end(void* tx_sem_id,
bool tx_enable,
srslte::rf_buffer_t& buffer,
uint32_t nof_samples,
srslte::rf_timestamp_t& tx_time)
{
// Wait for the green light to transmit in the current TTI
@ -537,10 +536,10 @@ void phy_common::worker_end(void* tx_sem_id,
if (tx_enable) {
if (ul_channel) {
ul_channel->run(buffer.to_cf_t(), buffer.to_cf_t(), nof_samples, tx_time.get(0));
ul_channel->run(buffer.to_cf_t(), buffer.to_cf_t(), buffer.get_nof_samples(), tx_time.get(0));
}
radio_h->tx(buffer, nof_samples, tx_time);
radio_h->tx(buffer, tx_time);
} else {
if (radio_h->is_continuous_tx()) {
if (is_pending_tx_end) {
@ -550,11 +549,12 @@ void phy_common::worker_end(void* tx_sem_id,
if (!radio_h->get_is_start_of_burst()) {
if (ul_channel) {
srslte_vec_cf_zero(zeros_multi.get(0), nof_samples);
ul_channel->run(zeros_multi.to_cf_t(), zeros_multi.to_cf_t(), nof_samples, tx_time.get(0));
srslte_vec_cf_zero(zeros_multi.get(0), buffer.get_nof_samples());
ul_channel->run(zeros_multi.to_cf_t(), zeros_multi.to_cf_t(), buffer.get_nof_samples(), tx_time.get(0));
}
radio_h->tx(zeros_multi, nof_samples, tx_time);
zeros_multi.set_nof_samples(buffer.get_nof_samples());
radio_h->tx(zeros_multi, tx_time);
}
}
} else {

View File

@ -39,8 +39,8 @@ namespace srsue {
static int
radio_recv_callback(void* obj, cf_t* data[SRSLTE_MAX_CHANNELS], uint32_t nsamples, srslte_timestamp_t* rx_time)
{
srslte::rf_buffer_t x(data);
return ((search_callback*)obj)->radio_recv_fnc(x, nsamples, rx_time);
srslte::rf_buffer_t x(data, nsamples);
return ((search_callback*)obj)->radio_recv_fnc(x, rx_time);
}
static SRSLTE_AGC_CALLBACK(callback_set_rx_gain)

View File

@ -202,9 +202,9 @@ void sf_worker::set_config(uint32_t cc_idx, srslte::phy_cfg_t& phy_cfg)
void sf_worker::work_imp()
{
srslte::rf_buffer_t tx_signal_ptr = {};
srslte::rf_buffer_t tx_signal_ptr = {};
if (!cell_initiated) {
phy->worker_end(this, false, tx_signal_ptr, 0, tx_time);
phy->worker_end(this, false, tx_signal_ptr, tx_time);
}
bool rx_signal_ok = false;
@ -255,6 +255,7 @@ void sf_worker::work_imp()
}
}
}
tx_signal_ptr.set_nof_samples(nof_samples);
// Set PRACH buffer signal pointer
if (prach_ptr) {
@ -264,7 +265,7 @@ void sf_worker::work_imp()
}
// Call worker_end to transmit the signal
phy->worker_end(this, tx_signal_ready, tx_signal_ptr, nof_samples, tx_time);
phy->worker_end(this, tx_signal_ready, tx_signal_ptr, tx_time);
if (rx_signal_ok) {
update_measurements();

View File

@ -45,8 +45,8 @@ namespace srsue {
static int
radio_recv_callback(void* obj, cf_t* data[SRSLTE_MAX_CHANNELS], uint32_t nsamples, srslte_timestamp_t* rx_time)
{
srslte::rf_buffer_t x(data);
return ((sync*)obj)->radio_recv_fnc(x, nsamples, rx_time);
srslte::rf_buffer_t x(data, nsamples);
return ((sync*)obj)->radio_recv_fnc(x, rx_time);
}
static SRSLTE_AGC_CALLBACK(callback_set_rx_gain)
@ -501,12 +501,13 @@ void sync::run_idle_state()
{
if (radio_h->is_init()) {
uint32_t nsamples = 1920;
if (current_srate > 0) {
if (std::isnormal(current_srate) and current_srate > 0.0f) {
nsamples = current_srate / 1000;
}
Debug("Discarding %d samples\n", nsamples);
srslte_timestamp_t rx_time = {};
if (radio_recv_fnc(dummy_buffer, nsamples, &rx_time) == SRSLTE_SUCCESS) {
dummy_buffer.set_nof_samples(nsamples);
if (radio_recv_fnc(dummy_buffer, &rx_time) == SRSLTE_SUCCESS) {
log_h->console("SYNC: Receiving from radio while in IDLE_RX\n");
}
// If radio is in locked state returns immediately. In that case, do a 1 ms sleep
@ -803,7 +804,7 @@ void sync::get_current_cell(srslte_cell_t* cell_, uint32_t* earfcn_)
}
}
int sync::radio_recv_fnc(srslte::rf_buffer_t& data, uint32_t nsamples, srslte_timestamp_t* rx_time)
int sync::radio_recv_fnc(srslte::rf_buffer_t& data, srslte_timestamp_t* rx_time)
{
// This function is designed for being called from the UE sync object which will pass a null rx_time in case
// receive dummy samples. So, rf_timestamp points at dummy timestamp in case rx_time is not provided
@ -811,70 +812,70 @@ int sync::radio_recv_fnc(srslte::rf_buffer_t& data, uint32_t nsamples, srslte_ti
srslte::rf_timestamp_t& rf_timestamp = (rx_time == nullptr) ? dummy_ts : last_rx_time;
// Receive
if (radio_h->rx_now(data, nsamples, rf_timestamp)) {
srslte_timestamp_t dummy_flat_ts = {};
// Load flat timestamp
if (rx_time == nullptr) {
rx_time = &dummy_flat_ts;
}
*rx_time = rf_timestamp.get(0);
// check timestamp reset
if (forced_rx_time_init || srslte_timestamp_iszero(&tti_ts) || srslte_timestamp_compare(rx_time, &tti_ts) < 0) {
if (srslte_timestamp_compare(rx_time, &tti_ts) < 0) {
log_h->warning("SYNC: radio time seems to be going backwards (rx_time=%f, tti_ts=%f)\n",
srslte_timestamp_real(rx_time),
srslte_timestamp_real(&tti_ts));
// time-stamp will be set to rx time below and run_tti() will be called with MIN_TTI_JUMP
}
// init tti_ts with last rx time
log_h->debug("SYNC: Setting initial TTI time to %f\n", srslte_timestamp_real(rx_time));
srslte_timestamp_copy(&tti_ts, rx_time);
forced_rx_time_init = false;
}
// Advance stack in time
if (srslte_timestamp_compare(rx_time, &tti_ts) >= 0) {
srslte_timestamp_t temp = {};
srslte_timestamp_copy(&temp, rx_time);
srslte_timestamp_sub(&temp, tti_ts.full_secs, tti_ts.frac_secs);
int32_t tti_jump = static_cast<int32_t>(srslte_timestamp_uint64(&temp, 1e3));
tti_jump = SRSLTE_MAX(tti_jump, MIN_TTI_JUMP);
if (tti_jump > MAX_TTI_JUMP) {
log_h->warning("SYNC: TTI jump of %d limited to %d\n", tti_jump, MAX_TTI_JUMP);
tti_jump = SRSLTE_MIN(tti_jump, MAX_TTI_JUMP);
}
// Run stack
stack->run_tti(tti, tti_jump);
}
// update timestamp
srslte_timestamp_copy(&tti_ts, rx_time);
if (channel_emulator && rx_time) {
channel_emulator->set_srate((uint32_t)current_srate);
channel_emulator->run(data.to_cf_t(), data.to_cf_t(), nsamples, *rx_time);
}
// Save signal for Intra-frequency measurement
if (srslte_cell_isvalid(&cell)) {
for (uint32_t i = 0; (uint32_t)i < intra_freq_meas.size(); i++) {
intra_freq_meas[i]->write(tti, data.get(i, 0, worker_com->args->nof_rx_ant), SRSLTE_SF_LEN_PRB(cell.nof_prb));
// Update RX gain
intra_freq_meas[i]->set_rx_gain_offset(worker_com->rx_gain_offset);
}
}
log_h->debug("SYNC: received %d samples from radio\n", nsamples);
return nsamples;
} else {
return -1;
if (not radio_h->rx_now(data, rf_timestamp)) {
return SRSLTE_ERROR;
}
srslte_timestamp_t dummy_flat_ts = {};
// Load flat timestamp
if (rx_time == nullptr) {
rx_time = &dummy_flat_ts;
}
*rx_time = rf_timestamp.get(0);
// check timestamp reset
if (forced_rx_time_init || srslte_timestamp_iszero(&tti_ts) || srslte_timestamp_compare(rx_time, &tti_ts) < 0) {
if (srslte_timestamp_compare(rx_time, &tti_ts) < 0) {
log_h->warning("SYNC: radio time seems to be going backwards (rx_time=%f, tti_ts=%f)\n",
srslte_timestamp_real(rx_time),
srslte_timestamp_real(&tti_ts));
// time-stamp will be set to rx time below and run_tti() will be called with MIN_TTI_JUMP
}
// init tti_ts with last rx time
log_h->debug("SYNC: Setting initial TTI time to %f\n", srslte_timestamp_real(rx_time));
srslte_timestamp_copy(&tti_ts, rx_time);
forced_rx_time_init = false;
}
// Advance stack in time
if (srslte_timestamp_compare(rx_time, &tti_ts) >= 0) {
srslte_timestamp_t temp = {};
srslte_timestamp_copy(&temp, rx_time);
srslte_timestamp_sub(&temp, tti_ts.full_secs, tti_ts.frac_secs);
int32_t tti_jump = static_cast<int32_t>(srslte_timestamp_uint64(&temp, 1e3));
tti_jump = SRSLTE_MAX(tti_jump, MIN_TTI_JUMP);
if (tti_jump > MAX_TTI_JUMP) {
log_h->warning("SYNC: TTI jump of %d limited to %d\n", tti_jump, MAX_TTI_JUMP);
tti_jump = SRSLTE_MIN(tti_jump, MAX_TTI_JUMP);
}
// Run stack
stack->run_tti(tti, tti_jump);
}
// update timestamp
srslte_timestamp_copy(&tti_ts, rx_time);
if (channel_emulator and rx_time) {
channel_emulator->set_srate((uint32_t)current_srate);
channel_emulator->run(data.to_cf_t(), data.to_cf_t(), data.get_nof_samples(), *rx_time);
}
// Save signal for Intra-frequency measurement
if (srslte_cell_isvalid(&cell)) {
for (uint32_t i = 0; (uint32_t)i < intra_freq_meas.size(); i++) {
intra_freq_meas[i]->write(tti, data.get(i, 0, worker_com->args->nof_rx_ant), SRSLTE_SF_LEN_PRB(cell.nof_prb));
// Update RX gain
intra_freq_meas[i]->set_rx_gain_offset(worker_com->rx_gain_offset);
}
}
log_h->debug("SYNC: received %d samples from radio\n", data.get_nof_samples());
return data.get_nof_samples();
}
void sync::set_rx_gain(float gain)

View File

@ -559,8 +559,8 @@ int main(int argc, char** argv)
if (radio) {
// Receive radio
srslte::rf_buffer_t radio_buffer(baseband_buffer);
radio->rx_now(radio_buffer, SRSLTE_SF_LEN_PRB(cell_base.nof_prb), ts);
srslte::rf_buffer_t radio_buffer(baseband_buffer, SRSLTE_SF_LEN_PRB(cell_base.nof_prb));
radio->rx_now(radio_buffer, ts);
} else {
// Run eNb simulator
bool put_pdsch = serving_cell_pdsch_enable;

View File

@ -191,9 +191,7 @@ private:
uint32_t get_count_late() { return count_late; }
bool tx(srslte::rf_buffer_interface& buffer,
const uint32_t& nof_samples,
const srslte::rf_timestamp_interface& tx_time) override
bool tx(srslte::rf_buffer_interface& buffer, const srslte::rf_timestamp_interface& tx_time) override
{
bool ret = true;
notify_tx();
@ -207,20 +205,20 @@ private:
}
tx_last_tx.copy(tx_time);
tx_last_tx.add((double)nof_samples / (double)tx_srate);
if (std::isnormal(tx_srate)) {
tx_last_tx.add((double)buffer.get_nof_samples() / (double)tx_srate);
}
return ret;
}
void release_freq(const uint32_t& carrier_idx) override{};
void tx_end() override {}
bool rx_now(srslte::rf_buffer_interface& buffer,
const uint32_t& nof_samples,
srslte::rf_timestamp_interface& rxd_time) override
bool rx_now(srslte::rf_buffer_interface& buffer, srslte::rf_timestamp_interface& rxd_time) override
{
notify_rx_now();
std::lock_guard<std::mutex> lock(mutex);
auto base_nsamples = (uint32_t)floorf(((float)nof_samples * base_srate) / rx_srate);
uint32_t base_nsamples = (uint32_t)floorf(((float)buffer.get_nof_samples() * base_srate) / rx_srate);
for (uint32_t i = 0; i < ring_buffers.size(); i++) {
cf_t* buf_ptr = ((buffer.get(i) != nullptr) && (base_srate == rx_srate)) ? buffer.get(i) : temp_buffer;
@ -240,7 +238,7 @@ private:
auto decimation = (uint32_t)roundf(base_srate / rx_srate);
// Perform decimation
for (uint32_t j = 0, k = 0; j < nof_samples; j++, k += decimation) {
for (uint32_t j = 0, k = 0; j < buffer.get_nof_samples(); j++, k += decimation) {
buffer.get(i)[j] = buf_ptr[k];
}
} else if (base_srate < rx_srate) {
@ -248,7 +246,7 @@ private:
auto interpolation = (uint32_t)roundf(rx_srate / base_srate);
// Perform zero order hold interpolation
for (uint32_t j = 0, k = 0; j < nof_samples; k++) {
for (uint32_t j = 0, k = 0; j < buffer.get_nof_samples(); k++) {
for (uint32_t c = 0; c < interpolation; c++, j++) {
buffer.get(i)[j] = buf_ptr[k];
}