NR-UE PHY transmits PRACH in all oportunities

master
Xavier Arteaga 4 years ago committed by Xavier Arteaga
parent df967d95b1
commit 10a7b63c6a

@ -38,23 +38,41 @@ typedef struct {
typedef struct {
srslte_sch_cfg_nr_t pdsch;
srslte_prach_cfg_t prach;
} phy_nr_cfg_t;
class phy_nr_state
{
public:
phy_nr_args_t args = {};
phy_nr_cfg_t cfg = {};
srslte_carrier_nr_t carrier = {};
phy_nr_args_t args = {};
phy_nr_cfg_t cfg = {};
phy_nr_state()
{
carrier.id = 0;
carrier.nof_prb = 100;
carrier.max_mimo_layers = 1;
// Default arguments
args.nof_carriers = 1;
args.dl.nof_rx_antennas = 1;
args.dl.nof_max_prb = 100;
args.dl.pdsch.measure_evm = true;
args.dl.pdsch.measure_time = true;
args.dl.pdsch.sch.disable_simd = false;
cfg.pdsch.sch_cfg.mcs_table = srslte_mcs_table_256qam;
// Default PDSCH configuration
cfg.pdsch.sch_cfg.mcs_table = srslte_mcs_table_256qam;
// Default PRACH configuration
cfg.prach.is_nr = true;
cfg.prach.config_idx = 16;
cfg.prach.root_seq_idx = 1;
cfg.prach.freq_offset = 0;
cfg.prach.zero_corr_zone = 0;
cfg.prach.num_ra_preambles = 64;
cfg.prach.hs_flag = false;
}
};

@ -40,7 +40,7 @@ namespace nr {
class sf_worker final : public srslte::thread_pool::worker
{
public:
sf_worker(phy_nr_state* phy_state_, srslte::log* log);
sf_worker(phy_common* phy, phy_nr_state* phy_state_, srslte::log* log);
~sf_worker() = default;
bool set_carrier_unlocked(uint32_t cc_idx, const srslte_carrier_nr_t* carrier_);
@ -52,14 +52,20 @@ public:
int read_pdsch_d(cf_t* pdsch_d);
void start_plot();
void set_prach(cf_t* prach_ptr, float prach_power);
private:
/* Inherited from thread_pool::worker. Function called every subframe to run the DL/UL processing */
void work_imp() override;
std::vector<std::unique_ptr<cc_worker> > cc_workers;
phy_common* phy = nullptr;
phy_nr_state* phy_state = nullptr;
srslte::log* log_h = nullptr;
cf_t* prach_ptr = nullptr;
float prach_power = 0;
};
} // namespace nr

@ -24,6 +24,7 @@
#include "sf_worker.h"
#include "srslte/common/thread_pool.h"
#include "srsue/hdr/phy/prach.h"
namespace srsue {
namespace nr {
@ -37,6 +38,7 @@ private:
srslte::thread_pool pool;
std::vector<std::unique_ptr<sf_worker> > workers;
phy_nr_state phy_state;
prach prach_buffer;
public:
sf_worker* operator[](std::size_t pos) { return workers.at(pos).get(); }
@ -44,7 +46,6 @@ public:
worker_pool(uint32_t max_workers);
bool init(phy_common* common, srslte::logger* logger, int prio);
sf_worker* wait_worker(uint32_t tti);
sf_worker* wait_worker_id(uint32_t id);
void start_worker(sf_worker* w);
void stop();
};

@ -123,7 +123,7 @@ public:
srslte_pdsch_ack_resource_t resource);
bool get_dl_pending_ack(srslte_ul_sf_cfg_t* sf, uint32_t cc_idx, srslte_pdsch_ack_cc_t* ack);
void worker_end(void* h, bool tx_enable, srslte::rf_buffer_t& buffer, srslte::rf_timestamp_t& tx_time);
void worker_end(void* h, bool tx_enable, srslte::rf_buffer_t& buffer, srslte::rf_timestamp_t& tx_time, bool is_nr);
void set_cell(const srslte_cell_t& c);
@ -318,6 +318,10 @@ private:
bool is_mch_subframe(srslte_mbsfn_cfg_t* cfg, uint32_t phy_tti);
bool is_mcch_subframe(srslte_mbsfn_cfg_t* cfg, uint32_t phy_tti);
// NR carriers buffering synchronization, LTE workers are in charge of transmitting
srslte::rf_buffer_t nr_tx_buffer;
bool nr_tx_buffer_ready = false;
};
} // namespace srsue

@ -171,7 +171,7 @@ void sf_worker::work_imp()
srslte::rf_buffer_t tx_signal_ptr = {};
if (!cell_initiated) {
phy->worker_end(this, false, tx_signal_ptr, tx_time);
phy->worker_end(this, false, tx_signal_ptr, tx_time, false);
return;
}
@ -243,7 +243,7 @@ void sf_worker::work_imp()
}
// Call worker_end to transmit the signal
phy->worker_end(this, tx_signal_ready, tx_signal_ptr, tx_time);
phy->worker_end(this, tx_signal_ready, tx_signal_ptr, tx_time, false);
if (rx_signal_ok) {
update_measurements();

@ -133,7 +133,8 @@ bool cc_worker::work_dl()
}
if (nof_found_dci < 1) {
ERROR("Error DCI not found");
// ERROR("Error DCI not found");
return true;
}
dci_dl.rnti = 0x1234;

@ -35,7 +35,8 @@ static int plot_worker_id = -1;
namespace srsue {
namespace nr {
sf_worker::sf_worker(phy_nr_state* phy_state_, srslte::log* log) : phy_state(phy_state_), log_h(log)
sf_worker::sf_worker(phy_common* phy_, phy_nr_state* phy_state_, srslte::log* log) :
phy_state(phy_state_), phy(phy_), log_h(log)
{
for (uint32_t i = 0; i < phy_state->args.nof_carriers; i++) {
cc_worker* w = new cc_worker(i, log, phy_state);
@ -76,11 +77,35 @@ void sf_worker::set_tti(uint32_t tti)
void sf_worker::work_imp()
{
srslte::rf_buffer_t tx_buffer = {};
srslte::rf_timestamp_t dummy_ts = {};
// Perform DL processing
for (auto& w : cc_workers) {
w->work_dl();
}
/* Tell the plotting thread to draw the plots */
// Check if PRACH is available
if (prach_ptr != nullptr) {
// PRACH is available, set buffer, transmit and return
tx_buffer.set(0, prach_ptr);
// Transmit NR PRACH
phy->worker_end(this, false, tx_buffer, dummy_ts, true);
// Reset PRACH pointer
prach_ptr = nullptr;
return;
}
// Perform UL processing
// ...
// Always call worker_end before returning
phy->worker_end(this, false, tx_buffer, dummy_ts, true);
// Tell the plotting thread to draw the plots
#ifdef ENABLE_GUI
if ((int)get_id() == plot_worker_id) {
sem_post(&plot_sem);
@ -108,6 +133,12 @@ void sf_worker::start_plot()
#endif
}
void sf_worker::set_prach(cf_t* prach_ptr_, float prach_power_)
{
prach_ptr = prach_ptr_;
prach_power = prach_power_;
}
} // namespace nr
} // namespace srsue
@ -120,7 +151,7 @@ extern bool plot_quit;
static void* plot_thread_run(void* arg)
{
auto worker = (srsue::nr::sf_worker*)arg;
auto worker = (srsue::nr::sf_worker*)arg;
int pdsch_re_count = 0;
while (!plot_quit) {
sem_wait(&plot_sem);

@ -27,6 +27,10 @@ worker_pool::worker_pool(uint32_t max_workers) : pool(max_workers) {}
bool worker_pool::init(phy_common* common, srslte::logger* logger, int prio)
{
// Set carrier attributes
phy_state.carrier.id = 0;
phy_state.carrier.nof_prb = common->args->nr_nof_prb;
// Set NR arguments
phy_state.args.nof_carriers = common->args->nof_nr_carriers;
phy_state.args.dl.nof_max_prb = common->args->nr_nof_prb;
@ -50,19 +54,32 @@ bool worker_pool::init(phy_common* common, srslte::logger* logger, int prio)
// Add workers to workers pool and start threads
for (uint32_t i = 0; i < common->args->nof_phy_threads; i++) {
auto w = new sf_worker(&phy_state, (srslte::log*)log_vec[i].get());
auto w = new sf_worker(common, &phy_state, (srslte::log*)log_vec[i].get());
pool.init_worker(i, w, prio, common->args->worker_cpu_mask);
workers.push_back(std::unique_ptr<sf_worker>(w));
srslte_carrier_nr_t c = {};
c.nof_prb = phy_state.args.dl.nof_max_prb;
c.max_mimo_layers = 1;
if (not w->set_carrier_unlocked(0, &c)) {
if (not w->set_carrier_unlocked(0, &phy_state.carrier)) {
return false;
}
}
// Initialise PRACH
auto* prach_log = new srslte::log_filter;
prach_log->init("NR-PRACH", logger, false);
prach_log->set_level(common->args->log.phy_level);
prach_log->set_hex_limit(common->args->log.phy_hex_limit);
log_vec.push_back(std::unique_ptr<srslte::log_filter>(prach_log));
prach_buffer.init(phy_state.args.dl.nof_max_prb, prach_log);
// Set PRACH hard-coded cell
srslte_cell_t cell = {};
cell.nof_prb = 50;
cell.id = phy_state.carrier.id;
if (not prach_buffer.set_cell(cell, phy_state.cfg.prach)) {
prach_log->error("Setting PRACH cell\n");
return false;
}
return true;
}
@ -73,12 +90,21 @@ void worker_pool::start_worker(sf_worker* w)
sf_worker* worker_pool::wait_worker(uint32_t tti)
{
return (sf_worker*)pool.wait_worker(tti);
}
sf_worker* worker = (sf_worker*)pool.wait_worker(tti);
sf_worker* worker_pool::wait_worker_id(uint32_t id)
{
return (sf_worker*)pool.wait_worker_id(id);
// Prepare PRACH, send always sequence 0
prach_buffer.prepare_to_send(0);
// Generate PRACH if ready
if (prach_buffer.is_ready_to_send(tti, phy_state.carrier.id)) {
uint32_t nof_prach_sf = 0;
float prach_target_power = 0.0f;
cf_t* prach_ptr = prach_buffer.generate(0.0f, &nof_prach_sf, &prach_target_power);
worker->set_prach(prach_ptr, prach_target_power);
log_vec.front().get()->info("tti=%d; Sending PRACH\n", tti);
}
return worker;
}
void worker_pool::stop()

@ -537,11 +537,35 @@ 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,
srslte::rf_timestamp_t& tx_time)
srslte::rf_timestamp_t& tx_time,
bool is_nr)
{
// Wait for the green light to transmit in the current TTI
semaphore.wait(tx_sem_id);
// If this is for NR, save Tx buffers...
if (is_nr) {
nr_tx_buffer = buffer;
nr_tx_buffer_ready = true;
semaphore.release();
return;
}
// ... otherwise, append NR base-band from saved buffer if available
if (nr_tx_buffer_ready) {
// Load NR carrier base-band
for (uint32_t i = 0; i < args->nof_nr_carriers * args->nof_rx_ant; i++) {
uint32 channel_idx = args->nof_lte_carriers * args->nof_rx_ant + i;
buffer.set(channel_idx, nr_tx_buffer.get(i));
}
// Remove NR buffer flag
nr_tx_buffer_ready = false;
// Make sure it transmits in this TTI
tx_enable = true;
}
// Add Time Alignment
tx_time.sub((double)ta.get_sec());

@ -496,15 +496,17 @@ void sync::run_camping_in_sync_state(lte::sf_worker* lte_worker,
}
}
// Start LTE worker
worker_com->semaphore.push(lte_worker);
lte_worker_pool->start_worker(lte_worker);
// Start NR worker only if present
if (nr_worker != nullptr) {
// NR worker needs to be launched first, phy_common::worker_end expects first the NR worker and the LTE worker.
nr_worker->set_tti(tti);
worker_com->semaphore.push(nr_worker);
nr_worker_pool->start_worker(nr_worker);
}
// Start LTE worker
worker_com->semaphore.push(lte_worker);
lte_worker_pool->start_worker(lte_worker);
}
void sync::run_camping_state()
{
@ -849,7 +851,7 @@ bool sync::set_frequency()
for (uint32_t i = 0; i < worker_com->args->nof_nr_carriers; i++) {
radio_h->set_rx_freq(i + worker_com->args->nof_lte_carriers, worker_com->args->nr_freq_hz);
// radio_h->set_tx_freq(0, set_ul_freq);
radio_h->set_tx_freq(i + worker_com->args->nof_lte_carriers, worker_com->args->nr_freq_hz);
}
ul_dl_factor = (float)(set_ul_freq / set_dl_freq);

Loading…
Cancel
Save