mirror of https://github.com/pvnis/srsRAN_4G.git
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
202 lines
6.7 KiB
C++
202 lines
6.7 KiB
C++
/**
|
|
*
|
|
* \section COPYRIGHT
|
|
*
|
|
* Copyright 2013-2021 Software Radio Systems Limited
|
|
*
|
|
* By using this file, you agree to the terms and conditions set
|
|
* forth in the LICENSE file which can be found at the top level of
|
|
* the distribution.
|
|
*
|
|
*/
|
|
|
|
#include <unistd.h>
|
|
|
|
#include "srsran/common/threads.h"
|
|
#include "srsran/srsran.h"
|
|
|
|
#include "srsenb/hdr/phy/txrx.h"
|
|
|
|
#define Error(fmt, ...) \
|
|
if (SRSRAN_DEBUG_ENABLED) \
|
|
logger.error(fmt, ##__VA_ARGS__)
|
|
#define Warning(fmt, ...) \
|
|
if (SRSRAN_DEBUG_ENABLED) \
|
|
logger.warning(fmt, ##__VA_ARGS__)
|
|
#define Info(fmt, ...) \
|
|
if (SRSRAN_DEBUG_ENABLED) \
|
|
logger.info(fmt, ##__VA_ARGS__)
|
|
#define Debug(fmt, ...) \
|
|
if (SRSRAN_DEBUG_ENABLED) \
|
|
logger.debug(fmt, ##__VA_ARGS__)
|
|
|
|
using namespace std;
|
|
|
|
namespace srsenb {
|
|
|
|
txrx::txrx(srslog::basic_logger& logger) : thread("TXRX"), logger(logger), running(false)
|
|
{
|
|
/* Do nothing */
|
|
}
|
|
|
|
bool txrx::init(stack_interface_phy_lte* stack_,
|
|
srsran::radio_interface_phy* radio_h_,
|
|
lte::worker_pool* lte_workers_,
|
|
nr::worker_pool* nr_workers_,
|
|
phy_common* worker_com_,
|
|
prach_worker_pool* prach_,
|
|
uint32_t prio_)
|
|
{
|
|
stack = stack_;
|
|
radio_h = radio_h_;
|
|
lte_workers = lte_workers_;
|
|
nr_workers = nr_workers_;
|
|
worker_com = worker_com_;
|
|
prach = prach_;
|
|
tx_worker_cnt = 0;
|
|
running = true;
|
|
|
|
nof_workers = lte_workers->get_nof_workers();
|
|
|
|
// Instantiate UL channel emulator
|
|
if (worker_com->params.ul_channel_args.enable) {
|
|
ul_channel = srsran::channel_ptr(
|
|
new srsran::channel(worker_com->params.ul_channel_args, worker_com->get_nof_rf_channels(), logger));
|
|
}
|
|
|
|
start(prio_);
|
|
return true;
|
|
}
|
|
|
|
void txrx::stop()
|
|
{
|
|
if (running) {
|
|
running = false;
|
|
wait_thread_finish();
|
|
}
|
|
}
|
|
|
|
void txrx::run_thread()
|
|
{
|
|
srsran::rf_buffer_t buffer = {};
|
|
srsran::rf_timestamp_t timestamp = {};
|
|
uint32_t sf_len = SRSRAN_SF_LEN_PRB(worker_com->get_nof_prb(0));
|
|
|
|
float samp_rate = srsran_sampling_freq_hz(worker_com->get_nof_prb(0));
|
|
|
|
// Configure radio
|
|
radio_h->set_rx_srate(samp_rate);
|
|
radio_h->set_tx_srate(samp_rate);
|
|
|
|
// Set Tx/Rx frequencies
|
|
for (uint32_t cc_idx = 0; cc_idx < worker_com->get_nof_carriers(); cc_idx++) {
|
|
double tx_freq_hz = worker_com->get_dl_freq_hz(cc_idx);
|
|
double rx_freq_hz = worker_com->get_ul_freq_hz(cc_idx);
|
|
uint32_t rf_port = worker_com->get_rf_port(cc_idx);
|
|
srsran::console("Setting frequency: DL=%.1f Mhz, UL=%.1f MHz for cc_idx=%d nof_prb=%d\n",
|
|
tx_freq_hz / 1e6f,
|
|
rx_freq_hz / 1e6f,
|
|
cc_idx,
|
|
worker_com->get_nof_prb(cc_idx));
|
|
radio_h->set_tx_freq(rf_port, tx_freq_hz);
|
|
radio_h->set_rx_freq(rf_port, rx_freq_hz);
|
|
}
|
|
|
|
// Set channel emulator sampling rate
|
|
if (ul_channel) {
|
|
ul_channel->set_srate(static_cast<uint32_t>(samp_rate));
|
|
}
|
|
|
|
logger.info("Starting RX/TX thread nof_prb=%d, sf_len=%d", worker_com->get_nof_prb(0), sf_len);
|
|
|
|
// Set TTI so that first TX is at tti=0
|
|
tti = TTI_SUB(0, FDD_HARQ_DELAY_UL_MS + 1);
|
|
|
|
// Main loop
|
|
while (running) {
|
|
tti = TTI_ADD(tti, 1);
|
|
logger.set_context(tti);
|
|
|
|
lte::sf_worker* lte_worker = nullptr;
|
|
if (worker_com->get_nof_carriers_lte() > 0) {
|
|
lte_worker = lte_workers->wait_worker(tti);
|
|
if (lte_worker == nullptr) {
|
|
// wait_worker() only returns NULL if it's being closed. Quit now to avoid unnecessary loops here
|
|
running = false;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
nr::sf_worker* nr_worker = nullptr;
|
|
if (worker_com->get_nof_carriers_nr() > 0) {
|
|
nr_worker = nr_workers->wait_worker(tti);
|
|
if (nr_worker == nullptr) {
|
|
running = false;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
// Multiple cell buffer mapping
|
|
{
|
|
uint32_t cc = 0;
|
|
for (uint32_t cc_lte = 0; cc_lte < worker_com->get_nof_carriers_lte(); cc_lte++, cc++) {
|
|
uint32_t rf_port = worker_com->get_rf_port(cc);
|
|
|
|
for (uint32_t p = 0; p < worker_com->get_nof_ports(cc); p++) {
|
|
// WARNING: The number of ports for all cells must be the same
|
|
buffer.set(rf_port, p, worker_com->get_nof_ports(0), lte_worker->get_buffer_rx(cc_lte, p));
|
|
}
|
|
}
|
|
for (uint32_t cc_nr = 0; cc_nr < worker_com->get_nof_carriers_lte(); cc_nr++, cc++) {
|
|
uint32_t rf_port = worker_com->get_rf_port(cc);
|
|
|
|
for (uint32_t p = 0; p < worker_com->get_nof_ports(cc); p++) {
|
|
// WARNING: The number of ports for all cells must be the same
|
|
buffer.set(rf_port, p, worker_com->get_nof_ports(0), nr_worker->get_buffer_rx(cc_nr, p));
|
|
}
|
|
}
|
|
}
|
|
|
|
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));
|
|
}
|
|
|
|
// Compute TX time: Any transmission happens in TTI+4 thus advance 4 ms the reception time
|
|
timestamp.add(FDD_HARQ_DELAY_UL_MS * 1e-3);
|
|
|
|
Debug("Setting TTI=%d, tx_mutex=%d, tx_time=%ld:%f to worker %d",
|
|
tti,
|
|
tx_worker_cnt,
|
|
timestamp.get(0).full_secs,
|
|
timestamp.get(0).frac_secs,
|
|
lte_worker->get_id());
|
|
|
|
lte_worker->set_time(tti, tx_worker_cnt, timestamp);
|
|
tx_worker_cnt = (tx_worker_cnt + 1) % nof_workers;
|
|
|
|
// Trigger prach worker execution
|
|
for (uint32_t cc = 0; cc < worker_com->get_nof_carriers_lte(); cc++) {
|
|
prach->new_tti(cc, tti, buffer.get(worker_com->get_rf_port(cc), 0, worker_com->get_nof_ports(0)));
|
|
}
|
|
|
|
// Launch NR worker only if available
|
|
if (nr_worker != nullptr) {
|
|
nr_worker->set_tti(tti);
|
|
worker_com->semaphore.push(nr_worker);
|
|
nr_workers->start_worker(nr_worker);
|
|
}
|
|
|
|
// Trigger phy worker execution
|
|
worker_com->semaphore.push(lte_worker);
|
|
lte_workers->start_worker(lte_worker);
|
|
|
|
// Advance stack in time
|
|
stack->tti_clock();
|
|
}
|
|
}
|
|
|
|
} // namespace srsenb
|