Integrates number of samples in radio buffer

Fix minor issue

Radio: Fix minor bug and add unit test
master
Xavier Arteaga 5 years ago committed by Xavier Arteaga
parent de230826b9
commit f04cf2090a

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

@ -56,6 +56,8 @@ public:
virtual void** to_void() = 0; virtual void** to_void() = 0;
virtual cf_t** to_cf_t() = 0; virtual cf_t** to_cf_t() = 0;
virtual uint32_t size() = 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. * the buffer object.
* *
* @param buffer Is the object that contains the pointers to all RF channels * @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 * @param tx_time Time to transmit all signals
* @return it returns true if the transmission was successful, otherwise it returns false * @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 * Indicates the radio to receive from all antennas and carriers synchronously and store the samples
* in the buffer object * in the buffer object
* *
* @param buffer Is the object where the samples will be stored * @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 * @param tx_time Time at which the samples were received. Note the time is the same for all carriers
* @return * @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 * Sets the TX frequency for all antennas in the provided carrier index

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

@ -57,17 +57,22 @@ public:
* contain up to SRSLTE_MAX_CHANNELS pointers * contain up to SRSLTE_MAX_CHANNELS pointers
* @param data Flat array to use as initializer for the internal buffer 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++) { for (uint32_t i = 0; i < SRSLTE_MAX_CHANNELS; i++) {
sample_buffer[i] = data[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 * 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 * @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 * Default constructor leaves the internal pointers to NULL
*/ */
@ -119,11 +124,14 @@ public:
void** to_void() override { return (void**)sample_buffer.data(); } void** to_void() override { return (void**)sample_buffer.data(); }
cf_t** to_cf_t() override { return sample_buffer.data(); } cf_t** to_cf_t() override { return sample_buffer.data(); }
uint32_t size() override { return nof_subframes * SRSLTE_SF_LEN_MAX; } 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: private:
std::array<cf_t*, SRSLTE_MAX_CHANNELS> sample_buffer = {}; std::array<cf_t*, SRSLTE_MAX_CHANNELS> sample_buffer = {};
bool allocated = false; bool allocated = false;
uint32_t nof_subframes = 0; uint32_t nof_subframes = 0;
uint32_t nof_samples = 0;
void free_all() void free_all()
{ {
for (uint32_t i = 0; i < SRSLTE_MAX_CHANNELS; i++) { for (uint32_t i = 0; i < SRSLTE_MAX_CHANNELS; i++) {

@ -88,7 +88,7 @@ int radio::init(const rf_args_t& args, phy_interface_radio* phy_)
// Split multiple RF channels using `;` delimiter // Split multiple RF channels using `;` delimiter
std::vector<std::string> device_args_list; 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 // Add auto if list is empty
if (device_args_list.empty()) { if (device_args_list.empty()) {
@ -211,7 +211,7 @@ bool radio::start_agc(bool tx_gain_same_rx)
return true; 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; 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++) { 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; 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, bool radio::rx_dev(const uint32_t& device_idx,
const rf_buffer_interface& buffer, const rf_buffer_interface& buffer,
const uint32_t& nof_samples,
srslte_timestamp_t* rxd_time) srslte_timestamp_t* rxd_time)
{ {
if (!is_initialized) { if (!is_initialized) {
@ -247,17 +246,17 @@ bool radio::rx_dev(const uint32_t& device_idx,
return false; return false;
} }
int ret = int ret = srslte_rf_recv_with_time_multi(
srslte_rf_recv_with_time_multi(&rf_devices[device_idx], radio_buffers, nof_samples, true, full_secs, frac_secs); &rf_devices[device_idx], radio_buffers, buffer.get_nof_samples(), true, full_secs, frac_secs);
return ret > 0; 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; bool ret = true;
for (uint32_t device_idx = 0; device_idx < (uint32_t)rf_devices.size(); device_idx++) { 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; 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, bool radio::tx_dev(const uint32_t& device_idx,
rf_buffer_interface& buffer, rf_buffer_interface& buffer,
const uint32_t& nof_samples_,
const srslte_timestamp_t& tx_time_) 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; uint32_t sample_offset = 0;
srslte_rf_t* rf_device = &rf_devices[device_idx]; srslte_rf_t* rf_device = &rf_devices[device_idx];

@ -25,6 +25,11 @@ if(RF_FOUND)
include_directories(${SRSGUI_INCLUDE_DIRS}) include_directories(${SRSGUI_INCLUDE_DIRS})
target_link_libraries(benchmark_radio ${SRSGUI_LIBRARIES}) target_link_libraries(benchmark_radio ${SRSGUI_LIBRARIES})
endif(SRSGUI_FOUND) 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) endif(RF_FOUND)

@ -39,7 +39,7 @@ using namespace srslte;
#define SRSLTE_MAX_RADIOS 3 #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 char radio_device[64];
static log_filter log_h; static log_filter log_h;
@ -77,9 +77,9 @@ void usage(char* prog)
printf("Usage: %s [foabcderpstvhmFxw]\n", prog); printf("Usage: %s [foabcderpstvhmFxw]\n", prog);
printf("\t-f Carrier frequency in Hz [Default %f]\n", freq); printf("\t-f Carrier frequency in Hz [Default %f]\n", freq);
printf("\t-g RF gain [Default AGC]\n"); printf("\t-g RF gain [Default AGC]\n");
printf("\t-a Arguments for first radio [Default %s]\n", radios_args[0]); 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]); 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]); 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-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-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); 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]; file_pattern = argv[optind];
break; break;
case 'a': case 'a':
strncpy(radios_args[0], argv[optind], 63); radios_args[0] = std::string(argv[optind]);
radios_args[0][63] = '\0';
break; break;
case 'b': case 'b':
strncpy(radios_args[1], argv[optind], 63); radios_args[1] = std::string(argv[optind]);
radios_args[1][63] = '\0';
break; break;
case 'c': case 'c':
strncpy(radios_args[2], argv[optind], 63); radios_args[2] = std::string(argv[optind]);
radios_args[2][63] = '\0';
break; break;
case 'd': case 'd':
strncpy(radio_device, argv[optind], 63); strncpy(radio_device, argv[optind], 63);
@ -409,7 +406,8 @@ int main(int argc, char** argv)
// receive each radio // receive each radio
for (uint32_t r = 0; r < nof_radios; r++) { 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 // run agc
@ -424,7 +422,8 @@ int main(int argc, char** argv)
for (uint32_t r = 0; r < nof_radios; r++) { for (uint32_t r = 0; r < nof_radios; r++) {
ts_tx.copy(ts_rx[r]); ts_tx.copy(ts_rx[r]);
ts_tx.add(0.004); 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);
} }
} }

@ -60,10 +60,9 @@ public:
* *
* @param tx_sem_id Semaphore identifier, the worker thread pointer is used * @param tx_sem_id Semaphore identifier, the worker thread pointer is used
* @param buffer baseband IQ sample buffer * @param buffer baseband IQ sample buffer
* @param nof_samples number of samples to transmit
* @param tx_time timestamp to transmit samples * @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 // Common objects
phy_args_t params = {}; phy_args_t params = {};

@ -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, void phy_common::worker_end(void* tx_sem_id,
srslte::rf_buffer_t& buffer, srslte::rf_buffer_t& buffer,
uint32_t nof_samples,
srslte::rf_timestamp_t& tx_time) srslte::rf_timestamp_t& tx_time)
{ {
// Wait for the green light to transmit in the current TTI // 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 // Run DL channel emulator if created
if (dl_channel) { 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 // Always transmit on single radio
radio->tx(buffer, nof_samples, tx_time); radio->tx(buffer, tx_time);
// Trigger MAC clock // Trigger MAC clock
stack->tti_clock(); stack->tti_clock();

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

@ -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) { if (ul_channel) {
ul_channel->run(buffer.to_cf_t(), buffer.to_cf_t(), sf_len, timestamp.get(0)); ul_channel->run(buffer.to_cf_t(), buffer.to_cf_t(), sf_len, timestamp.get(0));

@ -188,15 +188,14 @@ public:
} }
bool tx(srslte::rf_buffer_interface& buffer, bool tx(srslte::rf_buffer_interface& buffer,
const uint32_t& nof_samples,
const srslte::rf_timestamp_interface& tx_time) override const srslte::rf_timestamp_interface& tx_time) override
{ {
int err = SRSLTE_SUCCESS; int err = SRSLTE_SUCCESS;
// Get number of bytes to write // 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 // Write ring buffer
for (uint32_t i = 0; i < ringbuffers_tx.size() and err >= SRSLTE_SUCCESS; i++) { for (uint32_t i = 0; i < ringbuffers_tx.size() and err >= SRSLTE_SUCCESS; i++) {
@ -211,15 +210,14 @@ public:
} }
void tx_end() override {} void tx_end() override {}
bool rx_now(srslte::rf_buffer_interface& buffer, bool rx_now(srslte::rf_buffer_interface& buffer,
const uint32_t& nof_samples,
srslte::rf_timestamp_interface& rxd_time) override srslte::rf_timestamp_interface& rxd_time) override
{ {
int err = SRSLTE_SUCCESS; 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 // 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 // Write ring buffer
for (uint32_t i = 0; i < ringbuffers_rx.size() and err >= SRSLTE_SUCCESS; i++) { for (uint32_t i = 0; i < ringbuffers_rx.size() and err >= SRSLTE_SUCCESS; i++) {
@ -233,7 +231,7 @@ public:
// Copy new timestamp // Copy new timestamp
if (std::isnormal(rx_srate)) { 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 // Notify Rx

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

@ -31,7 +31,7 @@ namespace srsue {
class search_callback class search_callback
{ {
public: 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 void set_ue_sync_opts(srslte_ue_sync_t* q, float cfo) = 0;
virtual srslte::radio_interface_phy* get_radio() = 0; virtual srslte::radio_interface_phy* get_radio() = 0;
virtual void set_rx_gain(float gain) = 0; virtual void set_rx_gain(float gain) = 0;

@ -89,7 +89,7 @@ public:
// Other functions // Other functions
void set_rx_gain(float gain) override; 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; } srslte::radio_interface_phy* get_radio() override { return radio_h; }

@ -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, void phy_common::worker_end(void* tx_sem_id,
bool tx_enable, bool tx_enable,
srslte::rf_buffer_t& buffer, srslte::rf_buffer_t& buffer,
uint32_t nof_samples,
srslte::rf_timestamp_t& tx_time) srslte::rf_timestamp_t& tx_time)
{ {
// Wait for the green light to transmit in the current TTI // 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 (tx_enable) {
if (ul_channel) { 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 { } else {
if (radio_h->is_continuous_tx()) { if (radio_h->is_continuous_tx()) {
if (is_pending_tx_end) { 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 (!radio_h->get_is_start_of_burst()) {
if (ul_channel) { if (ul_channel) {
srslte_vec_cf_zero(zeros_multi.get(0), nof_samples); 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(), nof_samples, tx_time.get(0)); 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 { } else {

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

@ -202,9 +202,9 @@ void sf_worker::set_config(uint32_t cc_idx, srslte::phy_cfg_t& phy_cfg)
void sf_worker::work_imp() void sf_worker::work_imp()
{ {
srslte::rf_buffer_t tx_signal_ptr = {}; srslte::rf_buffer_t tx_signal_ptr = {};
if (!cell_initiated) { 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; 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 // Set PRACH buffer signal pointer
if (prach_ptr) { if (prach_ptr) {
@ -264,7 +265,7 @@ void sf_worker::work_imp()
} }
// Call worker_end to transmit the signal // 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) { if (rx_signal_ok) {
update_measurements(); update_measurements();

@ -45,8 +45,8 @@ namespace srsue {
static int static int
radio_recv_callback(void* obj, cf_t* data[SRSLTE_MAX_CHANNELS], uint32_t nsamples, srslte_timestamp_t* rx_time) 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); srslte::rf_buffer_t x(data, nsamples);
return ((sync*)obj)->radio_recv_fnc(x, nsamples, rx_time); return ((sync*)obj)->radio_recv_fnc(x, rx_time);
} }
static SRSLTE_AGC_CALLBACK(callback_set_rx_gain) static SRSLTE_AGC_CALLBACK(callback_set_rx_gain)
@ -501,12 +501,13 @@ void sync::run_idle_state()
{ {
if (radio_h->is_init()) { if (radio_h->is_init()) {
uint32_t nsamples = 1920; uint32_t nsamples = 1920;
if (current_srate > 0) { if (std::isnormal(current_srate) and current_srate > 0.0f) {
nsamples = current_srate / 1000; nsamples = current_srate / 1000;
} }
Debug("Discarding %d samples\n", nsamples); Debug("Discarding %d samples\n", nsamples);
srslte_timestamp_t rx_time = {}; 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"); 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 // 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 // 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 // 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; srslte::rf_timestamp_t& rf_timestamp = (rx_time == nullptr) ? dummy_ts : last_rx_time;
// Receive // Receive
if (radio_h->rx_now(data, nsamples, rf_timestamp)) { if (not radio_h->rx_now(data, rf_timestamp)) {
srslte_timestamp_t dummy_flat_ts = {}; return SRSLTE_ERROR;
}
// 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 srslte_timestamp_t dummy_flat_ts = {};
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 // Load flat timestamp
if (srslte_timestamp_compare(rx_time, &tti_ts) >= 0) { if (rx_time == nullptr) {
srslte_timestamp_t temp = {}; rx_time = &dummy_flat_ts;
srslte_timestamp_copy(&temp, rx_time); }
srslte_timestamp_sub(&temp, tti_ts.full_secs, tti_ts.frac_secs); *rx_time = rf_timestamp.get(0);
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 // check timestamp reset
stack->run_tti(tti, tti_jump); 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
} }
// update timestamp // 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); srslte_timestamp_copy(&tti_ts, rx_time);
forced_rx_time_init = false;
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); // 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);
} }
// Save signal for Intra-frequency measurement // Run stack
if (srslte_cell_isvalid(&cell)) { stack->run_tti(tti, tti_jump);
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 // update timestamp
intra_freq_meas[i]->set_rx_gain_offset(worker_com->rx_gain_offset); srslte_timestamp_copy(&tti_ts, rx_time);
}
}
log_h->debug("SYNC: received %d samples from radio\n", nsamples); 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);
}
return nsamples; // Save signal for Intra-frequency measurement
} else { if (srslte_cell_isvalid(&cell)) {
return -1; 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) void sync::set_rx_gain(float gain)

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

@ -191,9 +191,7 @@ private:
uint32_t get_count_late() { return count_late; } uint32_t get_count_late() { return count_late; }
bool tx(srslte::rf_buffer_interface& buffer, bool tx(srslte::rf_buffer_interface& buffer, const srslte::rf_timestamp_interface& tx_time) override
const uint32_t& nof_samples,
const srslte::rf_timestamp_interface& tx_time) override
{ {
bool ret = true; bool ret = true;
notify_tx(); notify_tx();
@ -207,20 +205,20 @@ private:
} }
tx_last_tx.copy(tx_time); 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; return ret;
} }
void release_freq(const uint32_t& carrier_idx) override{}; void release_freq(const uint32_t& carrier_idx) override{};
void tx_end() override {} void tx_end() override {}
bool rx_now(srslte::rf_buffer_interface& buffer, bool rx_now(srslte::rf_buffer_interface& buffer, srslte::rf_timestamp_interface& rxd_time) override
const uint32_t& nof_samples,
srslte::rf_timestamp_interface& rxd_time) override
{ {
notify_rx_now(); notify_rx_now();
std::lock_guard<std::mutex> lock(mutex); 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++) { 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; 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); auto decimation = (uint32_t)roundf(base_srate / rx_srate);
// Perform decimation // 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]; buffer.get(i)[j] = buf_ptr[k];
} }
} else if (base_srate < rx_srate) { } else if (base_srate < rx_srate) {
@ -248,7 +246,7 @@ private:
auto interpolation = (uint32_t)roundf(rx_srate / base_srate); auto interpolation = (uint32_t)roundf(rx_srate / base_srate);
// Perform zero order hold interpolation // 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++) { for (uint32_t c = 0; c < interpolation; c++, j++) {
buffer.get(i)[j] = buf_ptr[k]; buffer.get(i)[j] = buf_ptr[k];
} }

Loading…
Cancel
Save