SRSUE: Refactored asynchronous cell and ue_radio. CA Fixed.

This commit is contained in:
Xavier Arteaga 2019-05-16 14:57:13 +02:00 committed by Andre Puschmann
parent 65f50cd7ba
commit 080b4a327c
23 changed files with 273 additions and 261 deletions

View File

@ -656,7 +656,7 @@ public:
virtual void start_noncont_ho(uint32_t preamble_index, uint32_t prach_mask) = 0;
virtual void start_cont_ho() = 0;
virtual void reconfiguration() = 0;
virtual void reconfiguration(const uint32_t& cc_idx, const bool& enable) = 0;
virtual void reset() = 0;
virtual void wait_uplink() = 0;
};
@ -669,6 +669,9 @@ typedef struct {
float freq_offset;
float rx_gain;
float tx_gain;
float tx_max_power;
float tx_gain_offset;
float rx_gain_offset;
uint32_t nof_radios;
uint32_t nof_rf_channels; // Number of RF channels per radio
uint32_t nof_rx_ant; // Number of RF channels for MIMO
@ -868,31 +871,37 @@ class radio_interface_phy
{
public:
// trx functions
virtual bool tx(cf_t* buffer[SRSLTE_MAX_PORTS], const uint32_t& nof_samples, const srslte_timestamp_t& tx_time) = 0;
virtual bool tx(const uint32_t& radio_idx,
cf_t* buffer[SRSLTE_MAX_PORTS],
const uint32_t& nof_samples,
const srslte_timestamp_t& tx_time) = 0;
virtual void tx_end() = 0;
virtual bool rx_now(cf_t* buffer[SRSLTE_MAX_PORTS], const uint32_t& nof_samples, srslte_timestamp_t* rxd_time) = 0;
virtual bool rx_now(const uint32_t& radio_idx,
cf_t* buffer[SRSLTE_MAX_PORTS],
const uint32_t& nof_samples,
srslte_timestamp_t* rxd_time) = 0;
// setter
virtual void set_tx_freq(const uint32_t& radio_idx, const double& freq) = 0;
virtual void set_rx_freq(const uint32_t& radio_idx, const double& freq) = 0;
virtual void set_tx_freq(const uint32_t& radio_idx, const uint32_t& channel_idx, const double& freq) = 0;
virtual void set_rx_freq(const uint32_t& radio_idx, const uint32_t& channel_idx, const double& freq) = 0;
virtual double set_rx_gain_th(const float& gain) = 0;
virtual void set_rx_gain(const uint32_t& radio_idx, const float& gain) = 0;
virtual void set_master_clock_rate(const double& rate) = 0;
virtual void set_tx_srate(const double& srate) = 0;
virtual void set_rx_srate(const double& srate) = 0;
virtual float set_tx_power(const float& power) = 0;
virtual double set_rx_gain_th(const float& gain) = 0;
virtual void set_rx_gain(const uint32_t& radio_idx, const float& gain) = 0;
virtual void set_tx_srate(const uint32_t& radio_idx, const double& srate) = 0;
virtual void set_rx_srate(const uint32_t& radio_idx, const double& srate) = 0;
// getter
virtual float get_rx_gain(const uint32_t& radio_idx = 0) = 0;
virtual double get_freq_offset() = 0;
virtual double get_tx_freq(const uint32_t& radio_idx = 0) = 0;
virtual double get_rx_freq(const uint32_t& radio_idx = 0) = 0;
virtual float get_max_tx_power() = 0;
virtual bool is_continuous_tx() = 0;
virtual bool is_init() = 0;
virtual void reset() = 0;
virtual srslte_rf_info_t* get_info(const uint32_t& radio_idx = 0) = 0;
virtual float get_rx_gain(const uint32_t& radio_idx) = 0;
virtual double get_freq_offset() = 0;
virtual double get_tx_freq(const uint32_t& radio_idx) = 0;
virtual double get_rx_freq(const uint32_t& radio_idx) = 0;
virtual float get_max_tx_power() = 0;
virtual float get_tx_gain_offset() = 0;
virtual float get_rx_gain_offset() = 0;
virtual bool is_continuous_tx() = 0;
virtual bool is_init() = 0;
virtual void reset() = 0;
virtual srslte_rf_info_t* get_info(const uint32_t& radio_idx) = 0;
};
class phy_interface_radio

View File

@ -49,6 +49,7 @@ class radio {
burst_preamble_samples = 0;
burst_preamble_time_rounded = 0;
master_clock_rate = 0;
cur_tx_srate = 0;
tx_adv_sec = 0;
tx_adv_nsamples = 0;

View File

@ -179,20 +179,6 @@ void radio::get_time(srslte_timestamp_t* now)
srslte_rf_get_time(&rf_device, &now->full_secs, &now->frac_secs);
}
// TODO: Use Calibrated values for this
float radio::set_tx_power(float power)
{
if (power > 10) {
power = 10;
}
if (power < -50) {
power = -50;
}
float gain = power + 74;
srslte_rf_set_tx_gain(&rf_device, gain);
return gain;
}
float radio::get_max_tx_power()
{
return 40;
@ -304,13 +290,21 @@ double radio::set_rx_gain_th(float gain)
void radio::set_master_clock_rate(double rate)
{
srslte_rf_stop_rx_stream(&rf_device);
srslte_rf_set_master_clock_rate(&rf_device, rate);
srslte_rf_start_rx_stream(&rf_device, false);
if (rate != master_clock_rate) {
srslte_rf_stop_rx_stream(&rf_device);
srslte_rf_set_master_clock_rate(&rf_device, rate);
srslte_rf_start_rx_stream(&rf_device, false);
master_clock_rate = rate;
}
}
void radio::set_rx_srate(double srate)
{
if (srate < 10e6) {
set_master_clock_rate(4 * srate);
} else {
set_master_clock_rate(srate);
}
srslte_rf_set_rx_srate(&rf_device, srate);
}
@ -351,6 +345,11 @@ float radio::get_rx_gain()
void radio::set_tx_srate(double srate)
{
if (srate < 10e6) {
set_master_clock_rate(4 * srate);
} else {
set_master_clock_rate(srate);
}
cur_tx_srate = srslte_rf_set_tx_srate(&rf_device, srate);
burst_preamble_samples = (uint32_t) (cur_tx_srate * burst_preamble_sec);
if (burst_preamble_samples > burst_preamble_max_samples) {

View File

@ -315,13 +315,6 @@ int main(int argc, char** argv)
radio_h[r]->set_rx_gain(rf_gain);
}
// Set radio
if (srate < 10e6) {
radio_h[r]->set_master_clock_rate(4 * srate);
} else {
radio_h[r]->set_master_clock_rate(srate);
}
// Set Rx/Tx sampling rate
radio_h[r]->set_rx_srate(srate);
if (tx_enable) {

View File

@ -82,20 +82,6 @@ void txrx::run_thread()
uint32_t sf_len = SRSLTE_SF_LEN_PRB(worker_com->cell.nof_prb);
float samp_rate = srslte_sampling_freq_hz(worker_com->cell.nof_prb);
#if 0
if (30720%((int) samp_rate/1000) == 0) {
radio_h->set_master_clock_rate(30.72e6);
} else {
radio_h->set_master_clock_rate(23.04e6);
}
#else
if (samp_rate < 10e6) {
radio_h->set_master_clock_rate(4 * samp_rate);
} else {
radio_h->set_master_clock_rate(samp_rate);
}
#endif
log_h->console("Setting Sampling frequency %.2f MHz\n", (float) samp_rate/1000000);
// Configure radio

View File

@ -34,9 +34,17 @@
#include "srslte/radio/radio.h"
#include "srslte/srslte.h"
#include <cassert>
#include <cstdio>
#include <fstream>
#include <functional>
#include <iostream>
#include <memory>
#include <vector>
namespace srsue {
class async_scell_recv : public thread
class async_scell_recv : private thread
{
public:
async_scell_recv();
@ -75,14 +83,16 @@ private:
{
tti = 0;
bzero(&timestamp, sizeof(timestamp));
bzero(buffer, sizeof(buffer));
for (cf_t*& b : buffer) {
b = nullptr;
}
}
~phch_scell_recv_buffer()
{
for (int i = 0; i < SRSLTE_MAX_PORTS; i++) {
if (buffer[i]) {
free(buffer[i]);
for (cf_t*& b : buffer) {
if (b) {
free(b);
}
}
}
@ -115,7 +125,6 @@ private:
void reset();
void radio_error();
void set_ue_sync_opts(srslte_ue_sync_t* q, float cfo);
void run_thread();
void state_decode_mib();
void state_write_buffer();
@ -130,6 +139,7 @@ private:
bool running;
uint32_t tti;
uint32_t radio_idx;
// Pointers to other classes
srslte::log* log_h;
@ -168,8 +178,14 @@ private:
float dl_freq;
float ul_freq;
protected:
void run_thread() override;
};
typedef std::unique_ptr<async_scell_recv> async_scell_recv_ptr;
typedef std::vector<async_scell_recv_ptr> async_scell_recv_vector;
} // namespace srsue
#endif // SRSUE_ASYNCH_SCELL_RECV_H

View File

@ -95,7 +95,6 @@ private:
void set_uci_periodic_cqi(srslte_uci_data_t* uci_data);
void set_uci_aperiodic_cqi(srslte_uci_data_t* uci_data);
void set_uci_ack(srslte_uci_data_t* uci_data, bool is_grant_available, uint32_t dai_ul, bool is_pusch_available);
float set_power(float tx_power);
uint32_t get_wideband_cqi();
srslte_cqi_report_mode_t aperiodic_mode(asn1::rrc::cqi_report_mode_aperiodic_e mode);
void parse_antenna_info(asn1::rrc::phys_cfg_ded_s* dedicated);

View File

@ -157,7 +157,7 @@ private:
std::vector<sf_worker*> workers;
phy_common common;
sync sfsync;
async_scell_recv scell_sync[SRSLTE_MAX_RADIOS - 1];
async_scell_recv_vector scell_sync;
uint32_t scell_earfcn[SRSLTE_MAX_CARRIERS - 1];
prach prach_buffer;

View File

@ -53,7 +53,7 @@ public:
phy_common* _worker_com,
srslte::log* _log_h,
srslte::log* _log_phy_lib_h,
async_scell_recv* scell_sync_,
async_scell_recv_vector* scell_sync_,
uint32_t prio,
int sync_cpu_affinity = -1);
void stop();
@ -273,13 +273,13 @@ private:
// Pointers to other classes
stack_interface_phy_lte* stack;
srslte::log *log_h;
srslte::log* log_phy_lib_h;
srslte::thread_pool* workers_pool;
srslte::log* log_h;
srslte::log* log_phy_lib_h;
srslte::thread_pool* workers_pool;
radio_interface_phy* radio_h;
phy_common* worker_com;
prach *prach_buffer;
async_scell_recv* scell_sync;
phy_common* worker_com;
prach* prach_buffer;
async_scell_recv_vector* scell_sync;
// Object for synchronization of the primary cell
srslte_ue_sync_t ue_sync;

View File

@ -42,51 +42,66 @@ class ue_radio : public ue_radio_base, public radio_interface_phy
{
public:
ue_radio();
~ue_radio();
~ue_radio() override;
std::string get_type();
std::string get_type() override;
int init(const rf_args_t& args_, srslte::logger* logger_);
int init(const rf_args_t& args_, srslte::logger* logger_) override;
int init(const rf_args_t& args_, srslte::logger* logger_, phy_interface_radio* phy_);
void stop();
void stop() override;
static void rf_msg(srslte_rf_error_t error);
void handle_rf_msg(srslte_rf_error_t error);
bool get_metrics(rf_metrics_t* metrics);
bool get_metrics(rf_metrics_t* metrics) override;
// radio_interface_phy
bool is_init() { return radios.at(0)->is_init(); }
void reset() { return radios.at(0)->reset(); }
bool is_continuous_tx() { return radios.at(0)->is_continuous_tx(); }
bool tx(cf_t* buffer[SRSLTE_MAX_PORTS], const uint32_t& nof_samples, const srslte_timestamp_t& tx_time)
bool is_init() override { return radios.at(0)->is_init(); }
void reset() override { return radios.at(0)->reset(); }
bool is_continuous_tx() override { return radios.at(0)->is_continuous_tx(); }
bool tx(const uint32_t& radio_idx,
cf_t* buffer[SRSLTE_MAX_PORTS],
const uint32_t& nof_samples,
const srslte_timestamp_t& tx_time) override
{
for (auto& radio : radios) {
radio->tx(buffer, nof_samples, tx_time);
}
return true;
return radios.at(radio_idx)->tx(buffer, nof_samples, tx_time);
}
void tx_end() { return radios.at(0)->tx_end(); }
void tx_end() override { return radios.at(0)->tx_end(); }
bool rx_now(cf_t* buffer[SRSLTE_MAX_PORTS], const uint32_t& nof_samples, srslte_timestamp_t* rxd_time)
bool rx_now(const uint32_t& radio_idx,
cf_t* buffer[SRSLTE_MAX_PORTS],
const uint32_t& nof_samples,
srslte_timestamp_t* rxd_time) override
{
return radios.at(0)->rx_now(buffer, nof_samples, rxd_time);
return radios.at(radio_idx)->rx_now(buffer, nof_samples, rxd_time);
}
void set_rx_gain(const uint32_t& radio_idx, const float& gain) { radios.at(radio_idx)->set_rx_gain(gain); }
double set_rx_gain_th(const float& gain) { return radios.at(0)->set_rx_gain_th(gain); }
float get_rx_gain(const uint32_t& radio_idx) { return radios.at(radio_idx)->get_rx_gain(); }
void set_tx_freq(const uint32_t& radio_idx, const double& freq) { radios.at(radio_idx)->set_tx_freq(0, freq); }
void set_rx_freq(const uint32_t& radio_idx, const double& freq) { radios.at(radio_idx)->set_rx_freq(0, freq); }
double get_freq_offset() { return radios.at(0)->get_freq_offset(); }
double get_tx_freq(const uint32_t& radio_idx) { return radios.at(radio_idx)->get_tx_freq(); }
double get_rx_freq(const uint32_t& radio_idx) { return radios.at(radio_idx)->get_rx_freq(); }
float get_max_tx_power() { return radios.at(0)->get_max_tx_power(); }
void set_master_clock_rate(const double& rate) { radios.at(0)->set_master_clock_rate(rate); }
void set_tx_srate(const double& srate) { radios.at(0)->set_tx_srate(srate); }
void set_rx_srate(const double& srate) { radios.at(0)->set_rx_srate(srate); }
float set_tx_power(const float& power) { return radios.at(0)->set_tx_power(power); }
srslte_rf_info_t* get_info(const uint32_t& radio_idx) { return radios.at(radio_idx)->get_info(); }
void set_rx_gain(const uint32_t& radio_idx, const float& gain) override { radios.at(radio_idx)->set_rx_gain(gain); }
double set_rx_gain_th(const float& gain) override { return radios.at(0)->set_rx_gain_th(gain); }
float get_rx_gain(const uint32_t& radio_idx) override { return radios.at(radio_idx)->get_rx_gain(); }
void set_tx_freq(const uint32_t& radio_idx, const uint32_t& channel_idx, const double& freq) override
{
radios.at(radio_idx)->set_tx_freq(channel_idx, freq);
}
void set_rx_freq(const uint32_t& radio_idx, const uint32_t& channel_idx, const double& freq) override
{
radios.at(radio_idx)->set_rx_freq(channel_idx, freq);
}
double get_freq_offset() override { return radios.at(0)->get_freq_offset(); }
double get_tx_freq(const uint32_t& radio_idx) override { return radios.at(radio_idx)->get_tx_freq(); }
double get_rx_freq(const uint32_t& radio_idx) override { return radios.at(radio_idx)->get_rx_freq(); }
float get_max_tx_power() override { return args.tx_max_power; }
float get_tx_gain_offset() override { return args.tx_gain_offset; }
float get_rx_gain_offset() override { return args.rx_gain_offset; }
void set_tx_srate(const uint32_t& radio_idx, const double& srate) override
{
radios.at(radio_idx)->set_tx_srate(srate);
}
void set_rx_srate(const uint32_t& radio_idx, const double& srate) override
{
radios.at(radio_idx)->set_rx_srate(srate);
}
srslte_rf_info_t* get_info(const uint32_t& radio_idx) override { return radios.at(radio_idx)->get_info(); }
private:
srsue::rf_args_t args;

View File

@ -41,8 +41,6 @@ public:
ue_radio_base(){};
virtual ~ue_radio_base(){};
static std::shared_ptr<ue_radio_base> get_instance(const std::string& type);
virtual std::string get_type() = 0;
virtual int init(const srsue::rf_args_t& args_, srslte::logger* logger_) = 0;

View File

@ -131,6 +131,9 @@ private:
uint64_t nof_pkts;
};
typedef std::unique_ptr<dl_harq_entity> dl_harq_entity_ptr;
typedef std::vector<dl_harq_entity_ptr> dl_harq_entity_vector;
} // namespace srsue
#endif // SRSUE_DL_HARQ_H

View File

@ -49,11 +49,7 @@ class mac : public mac_interface_phy_lte,
{
public:
mac();
bool init(phy_interface_mac_lte* phy,
rlc_interface_mac* rlc,
rrc_interface_mac* rrc,
srslte::log* log_h,
uint32_t nof_carriers = 1);
bool init(phy_interface_mac_lte* phy, rlc_interface_mac* rlc, rrc_interface_mac* rrc, srslte::log* log_h);
void stop();
void get_metrics(mac_metrics_t m[SRSLTE_MAX_CARRIERS]);
@ -81,7 +77,7 @@ public:
void pcch_start_rx();
void setup_lcid(uint32_t lcid, uint32_t lcg, uint32_t priority, int PBR_x_tti, uint32_t BSD);
void mch_start_rx(uint32_t lcid);
void reconfiguration();
void reconfiguration(const uint32_t& cc_idx, const bool& enable);
void reset();
void wait_uplink();
@ -140,8 +136,9 @@ private:
demux demux_unit;
/* DL/UL HARQ */
std::vector<dl_harq_entity> dl_harq;
std::vector<ul_harq_entity> ul_harq;
dl_harq_entity_vector dl_harq;
ul_harq_entity_vector ul_harq;
ul_harq_cfg_t ul_harq_cfg;
/* MAC Uplink-related Procedures */
ra_proc ra_procedure;

View File

@ -117,6 +117,9 @@ private:
ra_proc* ra_procedure;
};
typedef std::unique_ptr<ul_harq_entity> ul_harq_entity_ptr;
typedef std::vector<ul_harq_entity_ptr> ul_harq_entity_vector;
} // namespace srsue
#endif // SRSUE_UL_HARQ_H

View File

@ -45,7 +45,7 @@
namespace srsue {
async_scell_recv::async_scell_recv()
async_scell_recv::async_scell_recv() : thread()
{
initiated = false;
buffer_write_idx = 0;
@ -55,6 +55,7 @@ async_scell_recv::async_scell_recv()
bzero(&cell, sizeof(srslte_cell_t));
bzero(sf_buffer, sizeof(sf_buffer));
running = false;
radio_idx = 1;
}
async_scell_recv::~async_scell_recv()
@ -63,9 +64,9 @@ async_scell_recv::~async_scell_recv()
srslte_ue_sync_free(&ue_sync);
}
for (int i = 0; i < SRSLTE_MAX_PORTS; i++) {
if (sf_buffer[i]) {
free(sf_buffer[i]);
for (auto& b : sf_buffer) {
if (b) {
free(b);
}
}
}
@ -113,7 +114,7 @@ void async_scell_recv::init(radio_interface_phy* _radio_handler, phy_common* _wo
return;
}
if (pthread_cond_init(&cvar_buffer, NULL)) {
if (pthread_cond_init(&cvar_buffer, nullptr)) {
fprintf(stderr, "Initiating condition var\n");
return;
}
@ -164,9 +165,9 @@ void async_scell_recv::set_agc_enable(bool enable)
do_agc = enable;
if (do_agc) {
if (radio_h) {
srslte_rf_info_t* rf_info = radio_h->get_info();
srslte_rf_info_t* rf_info = radio_h->get_info(radio_idx);
srslte_ue_sync_start_agc(
&ue_sync, callback_set_rx_gain, rf_info->min_rx_gain, rf_info->max_rx_gain, radio_h->get_rx_gain());
&ue_sync, callback_set_rx_gain, rf_info->min_rx_gain, rf_info->max_rx_gain, radio_h->get_rx_gain(radio_idx));
} else {
fprintf(stderr, "Error setting Secondary cell AGC: PHY not initiated\n");
}
@ -185,7 +186,7 @@ int async_scell_recv::radio_recv_fnc(cf_t* data[SRSLTE_MAX_PORTS], uint32_t nsam
int ret = 0;
if (running) {
if (radio_h->rx_now(data, nsamples, rx_time)) {
if (radio_h->rx_now(radio_idx, data, nsamples, rx_time)) {
log_h->debug("SYNC: received %d samples from radio\n", nsamples);
ret = nsamples;
} else {
@ -264,18 +265,17 @@ bool async_scell_recv::set_scell_cell(uint32_t carrier_idx, srslte_cell_t* _cell
// Get transceiver mapping
carrier_map_t* m = &worker_com->args->carrier_map[carrier_idx];
uint32_t channel_idx = m->channel_idx;
radio_idx = m->radio_idx;
// Set radio frequency if frequency changed
if (current_earfcn[channel_idx] != dl_earfcn && ret) {
if (current_earfcn[channel_idx] != dl_earfcn) {
dl_freq = srslte_band_fd(dl_earfcn) * 1e6f;
ul_freq = srslte_band_fu(srslte_band_ul_earfcn(dl_earfcn)) * 1e6f;
radio_h->set_rx_freq(channel_idx, dl_freq);
radio_h->set_tx_freq(channel_idx, ul_freq);
Info("Setting DL: %.1f MHz; UL %.1fMHz; Radio/Chan: %d/%d\n",
dl_freq / 1e6,
ul_freq / 1e6,
m->radio_idx,
m->channel_idx);
for (uint32_t p = 0; p < worker_com->args->nof_rx_ant; p++) {
radio_h->set_rx_freq(m->radio_idx, m->channel_idx + p, dl_freq);
radio_h->set_tx_freq(m->radio_idx, m->channel_idx + p, ul_freq);
}
Info("Setting DL: %.1f MHz; UL %.1fMHz; Radio/Chan: %d/%d\n", dl_freq / 1e6, ul_freq / 1e6, radio_idx, channel_idx);
ul_dl_factor = ul_freq / dl_freq;
current_earfcn[channel_idx] = dl_earfcn;
reset_ue_sync = true;
@ -284,15 +284,10 @@ bool async_scell_recv::set_scell_cell(uint32_t carrier_idx, srslte_cell_t* _cell
// Detect change in cell configuration
if (memcmp(&cell, _cell, sizeof(srslte_cell_t)) != 0) {
// Set sampling rate, if number of PRB changed
if (cell.nof_prb != _cell->nof_prb && ret) {
if (cell.nof_prb != _cell->nof_prb) {
double srate = srslte_sampling_freq_hz(_cell->nof_prb);
if (srate < 10e6) {
radio_h->set_master_clock_rate(4 * srate);
} else {
radio_h->set_master_clock_rate(srate);
}
radio_h->set_rx_srate(srate);
radio_h->set_tx_srate(srate);
radio_h->set_rx_srate(radio_idx, srate);
radio_h->set_tx_srate(radio_idx, srate);
Info("Setting SRate to %.2f MHz\n", srate / 1e6);
}
@ -344,7 +339,7 @@ void async_scell_recv::state_decode_mib()
if (sfidx == 0) {
// Run only for sub-frame index 0
int n = srslte_ue_mib_decode(&ue_mib, bch_payload, NULL, &sfn_offset);
int n = srslte_ue_mib_decode(&ue_mib, bch_payload, nullptr, &sfn_offset);
if (n < SRSLTE_SUCCESS) {
// Error decoding MIB, log error
@ -502,10 +497,10 @@ bool async_scell_recv::tti_align(uint32_t tti)
bool timedout = false;
while (!ret && !timedout && buffer_write_idx == buffer_read_idx && running) {
struct timespec timeToWait;
struct timeval now;
struct timespec timeToWait = {};
struct timeval now = {};
gettimeofday(&now, NULL);
gettimeofday(&now, nullptr);
timeToWait.tv_sec = now.tv_sec;
timeToWait.tv_nsec = (now.tv_usec + 1000UL) * 1000UL;

View File

@ -115,6 +115,7 @@ cc_worker::cc_worker(uint32_t cc_idx, uint32_t max_prb, srsue::phy_common* phy,
ue_dl.pdsch.llr_is_8bit = true;
ue_dl.pdsch.dl_sch.llr_is_8bit = true;
}
pregen_enabled = false;
}
cc_worker::~cc_worker()
@ -942,21 +943,6 @@ void cc_worker::set_uci_ack(srslte_uci_data_t* uci_data,
srslte_ue_dl_gen_ack(&ue_dl, &sf_cfg_dl, &ack_info, uci_data);
}
float cc_worker::set_power(float tx_power)
{
float gain = 0;
/* Check if UL power control is enabled */
if (phy->args->ul_pwr_ctrl_en) {
/* Adjust maximum power if it changes significantly */
if (tx_power < phy->cur_radio_power - 5 || tx_power > phy->cur_radio_power + 5) {
phy->cur_radio_power = tx_power;
float radio_tx_power = phy->cur_radio_power;
gain = phy->get_radio()->set_tx_power(radio_tx_power);
}
}
return gain;
}
/************
*
* Configuration Functions

View File

@ -42,13 +42,12 @@ using namespace asn1::rrc;
namespace srsue {
phy::phy() : workers_pool(MAX_WORKERS), workers(0), common(MAX_WORKERS)
phy::phy() : workers_pool(MAX_WORKERS), workers(0), common(MAX_WORKERS), scell_sync()
{
tdd_config = {};
prach_cfg = {};
args = {};
ZERO_OBJECT(scell_earfcn);
ZERO_OBJECT(scell_sync);
n_ta = 0;
initiated = false;
}
@ -194,7 +193,9 @@ void phy::run_thread()
// Load Asynchronous SCell objects
for (int i = 0; i < (int)args.nof_radios - 1; i++) {
scell_sync[i].init(&radio[i + 1], &common, log_h);
auto t = async_scell_recv_ptr(new async_scell_recv());
t->init(radio, &common, log_h);
scell_sync.push_back(std::move(t));
}
// Warning this must be initialized after all workers have been added to the pool
@ -205,7 +206,7 @@ void phy::run_thread()
&common,
log_h,
log_phy_lib_h,
scell_sync,
&scell_sync,
SF_RECV_THREAD_PRIO,
args.sync_cpu_affinity);
@ -229,7 +230,7 @@ void phy::stop()
if (initiated) {
sfsync.stop();
for (uint32_t i = 0; i < args.nof_radios - 1; i++) {
scell_sync[i].stop();
scell_sync.at(i)->stop();
}
workers_pool.stop();
@ -489,14 +490,16 @@ void phy::set_config_scell(asn1::rrc::scell_to_add_mod_r10_s* scell_config)
// If SCell does not share synchronism with PCell ...
if (m->radio_idx > 0) {
scell_sync[m->radio_idx - 1].set_scell_cell(cc_idx, &cell, earfcn);
scell_sync.at(m->radio_idx - 1)->set_scell_cell(cc_idx, &cell, earfcn);
} else {
// Change frequency only if the earfcn was modified
if (scell_earfcn[cc_idx - 1] != earfcn) {
float dl_freq = srslte_band_fd(earfcn) * 1e6f;
float ul_freq = srslte_band_fu(srslte_band_ul_earfcn(earfcn)) * 1e6f;
radio->set_rx_freq(m->channel_idx, dl_freq);
radio->set_tx_freq(m->channel_idx, ul_freq);
for (uint32_t p = 0; p < common.args->nof_rx_ant; p++) {
radio->set_rx_freq(m->radio_idx, m->channel_idx + p, dl_freq);
radio->set_tx_freq(m->radio_idx, m->channel_idx + p, ul_freq);
}
}
}

View File

@ -565,16 +565,16 @@ void phy_common::worker_end(uint32_t tti,
// For each radio, transmit
for (uint32_t i = 0; i < args->nof_radios; i++) {
if (tx_enable && !srslte_timestamp_iszero(&tx_time[i])) {
radio_h[i].tx(buffer[i], nof_samples[i], tx_time[i]);
radio_h->tx(i, buffer[i], nof_samples[i], tx_time[i]);
is_first_of_burst[i] = false;
} else {
if (radio_h[i].is_continuous_tx()) {
if (radio_h->is_continuous_tx()) {
if (!is_first_of_burst[i]) {
radio_h[i].tx(zeros_multi, nof_samples[i], tx_time[i]);
radio_h->tx(i, zeros_multi, nof_samples[i], tx_time[i]);
}
} else {
if (!is_first_of_burst[i]) {
radio_h[i].tx_end();
radio_h->tx_end();
is_first_of_burst[i] = true;
}
}

View File

@ -331,7 +331,7 @@ void sf_worker::update_measurements()
}
if (!rssi_read_cnt) {
phy->rx_gain_offset = phy->get_radio()->get_rx_gain() + phy->args->rx_gain_offset;
phy->rx_gain_offset = phy->get_radio()->get_rx_gain(0) + phy->args->rx_gain_offset;
}
rssi_read_cnt++;
if (rssi_read_cnt == 1000) {

View File

@ -66,7 +66,7 @@ void sync::init(radio_interface_phy* _radio,
phy_common* _worker_com,
srslte::log* _log_h,
srslte::log* _log_phy_lib_h,
async_scell_recv* scell_sync_,
async_scell_recv_vector* scell_sync_,
uint32_t prio,
int sync_cpu_affinity)
{
@ -476,8 +476,8 @@ void sync::run_thread()
srslte_timestamp_init(&tx_time, 0, 0);
// Request TTI aligment
if (scell_sync[i].tti_align(tti)) {
scell_sync[i].read_sf(buffer[i + 1], &tx_time);
if (scell_sync->at(i)->tti_align(tti)) {
scell_sync->at(i)->read_sf(buffer[i + 1], &tx_time);
srslte_timestamp_add(&tx_time, 0, TX_DELAY * 1e-3 - time_adv_sec);
} else {
// Failed, keep default Timestamp
@ -572,7 +572,7 @@ void sync::run_thread()
}
Debug("Discarting %d samples\n", nsamples);
srslte_timestamp_t rx_time;
if (!radio_h->rx_now(dummy_buffer, nsamples, &rx_time)) {
if (!radio_h->rx_now(0, dummy_buffer, nsamples, &rx_time)) {
log_h->console("SYNC: Receiving from radio while in IDLE_RX\n");
}
// If radio is in locked state returns inmidiatetly. In that case, do a 1 ms sleep
@ -699,12 +699,9 @@ void sync::set_agc_enable(bool enable)
do_agc = enable;
if (do_agc) {
if (running && radio_h) {
srslte_rf_info_t *rf_info = radio_h->get_info();
srslte_ue_sync_start_agc(&ue_sync,
callback_set_rx_gain,
rf_info->min_rx_gain,
rf_info->max_rx_gain,
radio_h->get_rx_gain());
srslte_rf_info_t* rf_info = radio_h->get_info(0);
srslte_ue_sync_start_agc(
&ue_sync, callback_set_rx_gain, rf_info->min_rx_gain, rf_info->max_rx_gain, radio_h->get_rx_gain(0));
search_p.set_agc_enable(true);
} else {
ERROR("Error setting AGC: PHY not initiatec\n");
@ -852,11 +849,11 @@ bool sync::set_frequency()
carrier_map_t* m = &worker_com->args->carrier_map[0];
for (uint32_t i = 0; i < worker_com->args->nof_rx_ant; i++) {
radio_h->set_rx_freq(m->channel_idx + i, set_dl_freq);
radio_h->set_tx_freq(m->channel_idx + i, set_ul_freq);
radio_h->set_rx_freq(m->radio_idx, m->channel_idx + i, set_dl_freq);
radio_h->set_tx_freq(m->radio_idx, m->channel_idx + i, set_ul_freq);
}
ul_dl_factor = (float)(radio_h->get_tx_freq() / radio_h->get_rx_freq());
ul_dl_factor = (float)(radio_h->get_tx_freq(m->radio_idx) / radio_h->get_rx_freq(m->radio_idx));
srslte_ue_sync_reset(&ue_sync);
@ -875,23 +872,9 @@ void sync::set_sampling_rate()
current_srate = new_srate;
Info("SYNC: Setting sampling rate %.2f MHz\n", current_srate/1000000);
#if 0
if (((int) current_srate / 1000) % 3072 == 0) {
radio_h->set_master_clock_rate(30.72e6);
} else {
radio_h->set_master_clock_rate(23.04e6);
}
#else
if (current_srate < 10e6) {
radio_h->set_master_clock_rate(4 * current_srate);
} else {
radio_h->set_master_clock_rate(current_srate);
}
#endif
srate_mode = SRATE_CAMP;
radio_h->set_rx_srate(current_srate);
radio_h->set_tx_srate(current_srate);
radio_h->set_rx_srate(0, current_srate);
radio_h->set_tx_srate(0, current_srate);
} else {
Error("Error setting sampling rate for cell with %d PRBs\n", cell.nof_prb);
}
@ -914,7 +897,7 @@ void sync::get_current_cell(srslte_cell_t* cell, uint32_t* earfcn)
int sync::radio_recv_fnc(cf_t* data[SRSLTE_MAX_PORTS], uint32_t nsamples, srslte_timestamp_t* rx_time)
{
if (radio_h->rx_now(data, nsamples, rx_time)) {
if (radio_h->rx_now(0, data, nsamples, rx_time)) {
int offset = nsamples - current_sflen;
if (abs(offset) < 10 && offset != 0) {
next_offset += offset;
@ -987,12 +970,12 @@ float sync::search::get_last_cfo()
void sync::search::set_agc_enable(bool enable)
{
if (enable) {
srslte_rf_info_t *rf_info = p->radio_h->get_info();
srslte_rf_info_t* rf_info = p->radio_h->get_info(0);
srslte_ue_sync_start_agc(&ue_mib_sync.ue_sync,
callback_set_rx_gain,
rf_info->min_rx_gain,
rf_info->max_rx_gain,
p->radio_h->get_rx_gain());
p->radio_h->get_rx_gain(0));
} else {
ERROR("Error stop AGC not implemented\n");
}
@ -1014,8 +997,8 @@ sync::search::ret_code sync::search::run(srslte_cell_t* cell)
if (p->srate_mode != SRATE_FIND) {
p->srate_mode = SRATE_FIND;
p->radio_h->set_rx_srate(1.92e6);
p->radio_h->set_tx_srate(1.92e6);
p->radio_h->set_rx_srate(0, 1.92e6);
p->radio_h->set_tx_srate(0, 1.92e6);
Info("SYNC: Setting Cell Search sampling rate\n");
}

View File

@ -71,14 +71,14 @@ int ue_radio::init(const rf_args_t& args_, srslte::logger* logger_)
}
// Init and start Radio
char* dev_name = NULL;
if (args.device_name.compare("auto")) {
char* dev_name = nullptr;
if (args.device_name != "auto") {
dev_name = (char*)args.device_name.c_str();
}
char* dev_args[SRSLTE_MAX_RADIOS] = {NULL};
char* dev_args[SRSLTE_MAX_RADIOS] = {nullptr};
for (int i = 0; i < SRSLTE_MAX_RADIOS; i++) {
if (args.device_args[0].compare("auto")) {
if (args.device_args[i] != "auto") {
dev_args[i] = (char*)args.device_args[i].c_str();
}
}
@ -93,17 +93,16 @@ int ue_radio::init(const rf_args_t& args_, srslte::logger* logger_)
}
// Set RF options
if (args.time_adv_nsamples.compare("auto")) {
int t = atoi(args.time_adv_nsamples.c_str());
if (args.time_adv_nsamples == "auto") {
int t = (int)strtol(args.time_adv_nsamples.c_str(), nullptr, 10);
radio->set_tx_adv(abs(t));
radio->set_tx_adv_neg(t < 0);
}
if (args.burst_preamble.compare("auto")) {
radio->set_burst_preamble(atof(args.burst_preamble.c_str()));
if (args.burst_preamble == "auto") {
radio->set_burst_preamble(strtof(args.burst_preamble.c_str(), nullptr));
}
if (args.continuous_tx.compare("auto")) {
log.console("set continuous %s\n", args.continuous_tx.c_str());
radio->set_continuous_tx(args.continuous_tx.compare("yes") ? false : true);
if (args.continuous_tx == "auto") {
radio->set_continuous_tx(!(args.continuous_tx == "yes"));
}
// Set PHY options

View File

@ -37,24 +37,24 @@ using namespace asn1::rrc;
namespace srsue {
mac::mac() :
timers(64),
pdu_process_thread(&demux_unit),
mch_msg(10),
dl_harq(SRSLTE_MAX_CARRIERS),
ul_harq(SRSLTE_MAX_CARRIERS),
running(false),
pcap(NULL)
mac::mac() : timers(64), pdu_process_thread(&demux_unit), mch_msg(10), running(false), pcap(nullptr)
{
// Create PCell HARQ entities
auto ul = ul_harq_entity_ptr(new ul_harq_entity());
auto dl = dl_harq_entity_ptr(new dl_harq_entity());
ul_harq.clear();
dl_harq.clear();
ul_harq.push_back(std::move(ul));
dl_harq.push_back(std::move(dl));
// Keep initialising members
bzero(&metrics, sizeof(mac_metrics_t));
clear_rntis();
}
bool mac::init(phy_interface_mac_lte* phy,
rlc_interface_mac* rlc,
rrc_interface_mac* rrc,
srslte::log* log_h_,
uint32_t nof_carriers)
bool mac::init(phy_interface_mac_lte* phy, rlc_interface_mac* rlc, rrc_interface_mac* rrc, srslte::log* log_h_)
{
phy_h = phy;
rlc_h = rlc;
@ -75,10 +75,9 @@ bool mac::init(phy_interface_mac_lte* phy,
phy_h, rrc, log_h, &uernti, timers.get(timer_alignment), timers.get(contention_resolution_timer), &mux_unit);
sr_procedure.init(phy_h, rrc, log_h);
for (uint32_t r = 0; r < nof_carriers; r++) {
ul_harq[r].init(log_h, &uernti, &ra_procedure, &mux_unit);
dl_harq[r].init(log_h, &uernti, timers.get(timer_alignment), &demux_unit);
}
// Create UL/DL unique HARQ pointers
ul_harq.at(0)->init(log_h, &uernti, &ra_procedure, &mux_unit);
dl_harq.at(0)->init(log_h, &uernti, timers.get(timer_alignment), &demux_unit);
reset();
@ -103,19 +102,32 @@ void mac::stop()
void mac::start_pcap(srslte::mac_pcap* pcap_)
{
pcap = pcap_;
for (uint32_t r = 0; r < dl_harq.size(); r++) {
dl_harq[r].start_pcap(pcap);
for (auto& r : dl_harq) {
r->start_pcap(pcap);
}
for (uint32_t r = 0; r < ul_harq.size(); r++) {
ul_harq[r].start_pcap(pcap);
for (auto& r : ul_harq) {
r->start_pcap(pcap);
}
ra_procedure.start_pcap(pcap);
}
// Implement Section 5.8
void mac::reconfiguration()
void mac::reconfiguration(const uint32_t& cc_idx, const bool& enable)
{
if (cc_idx < SRSLTE_MAX_CARRIERS) {
// Create as many HARQ entities as carriers required
while (ul_harq.size() < cc_idx + 1) {
auto ul = ul_harq_entity_ptr(new ul_harq_entity());
ul->init(log_h, &uernti, &ra_procedure, &mux_unit);
ul->set_config(ul_harq_cfg);
ul_harq.push_back(std::move(ul));
}
while (dl_harq.size() < cc_idx + 1) {
auto dl = dl_harq_entity_ptr(new dl_harq_entity());
dl->init(log_h, &uernti, timers.get(timer_alignment), &demux_unit);
dl_harq.push_back(std::move(dl));
}
}
}
void mac::wait_uplink() {
@ -138,11 +150,11 @@ void mac::reset()
timer_alignment_expire();
for (uint32_t r = 0; r < dl_harq.size(); r++) {
dl_harq[r].reset();
for (auto& r : dl_harq) {
r->reset();
}
for (uint32_t r = 0; r < ul_harq.size(); r++) {
ul_harq[r].reset();
for (auto& r : ul_harq) {
r->reset();
}
mux_unit.msg3_flush();
@ -210,9 +222,7 @@ void mac::run_thread()
void mac::bcch_start_rx(int si_window_start, int si_window_length)
{
if (si_window_length >= 0 && si_window_start >= 0) {
for (uint32_t r = 0; r < dl_harq.size(); r++) {
dl_harq[r].set_si_window_start(si_window_start);
}
dl_harq.at(0)->set_si_window_start(si_window_start);
this->si_window_length = si_window_length;
this->si_window_start = si_window_start;
} else {
@ -383,7 +393,7 @@ void mac::tb_decoded(uint32_t cc_idx, mac_grant_dl_t grant, bool ack[SRSLTE_MAX_
}
} else {
dl_harq[cc_idx].tb_decoded(grant, ack);
dl_harq.at(cc_idx)->tb_decoded(grant, ack);
pdu_process_thread.notify();
for (uint32_t tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb++) {
@ -423,7 +433,7 @@ void mac::new_grant_dl(uint32_t cc_idx,
if (grant.rnti == uernti.crnti && ra_procedure.is_contention_resolution()) {
ra_procedure.pdcch_to_crnti(false);
}
dl_harq[cc_idx].new_grant_dl(grant, action);
dl_harq.at(cc_idx)->new_grant_dl(grant, action);
} else {
/* Discard */
Info("Discarding dci in CC %d, RNTI=0x%x\n", cc_idx, grant.rnti);
@ -438,8 +448,8 @@ uint32_t mac::get_current_tti()
void mac::reset_harq(uint32_t cc_idx)
{
if (cc_idx < dl_harq.size()) {
dl_harq[cc_idx].reset();
ul_harq[cc_idx].reset();
dl_harq.at(cc_idx)->reset();
ul_harq.at(cc_idx)->reset();
}
}
@ -457,14 +467,14 @@ void mac::new_grant_ul(uint32_t cc_idx,
is_first_ul_grant = false;
phr_procedure.start_timer();
}
ul_harq[cc_idx].new_grant_ul(grant, action);
ul_harq.at(cc_idx)->new_grant_ul(grant, action);
metrics[cc_idx].tx_pkts++;
if (grant.phich_available) {
if (!grant.hi_value) {
metrics[cc_idx].tx_errors++;
} else {
metrics[cc_idx].tx_brate += ul_harq[cc_idx].get_current_tbs(grant.pid) * 8;
metrics[cc_idx].tx_brate += ul_harq.at(cc_idx)->get_current_tbs(grant.pid) * 8;
}
}
}
@ -503,11 +513,11 @@ void mac::timer_expired(uint32_t timer_id)
void mac::timer_alignment_expire()
{
rrc_h->release_pucch_srs();
for (uint32_t r = 0; r < dl_harq.size(); r++) {
dl_harq[r].reset();
for (auto& r : dl_harq) {
r->reset();
}
for (uint32_t r = 0; r < ul_harq.size(); r++) {
ul_harq[r].reset();
for (auto& r : ul_harq) {
r->reset();
}
}
@ -539,8 +549,11 @@ void mac::set_config(mac_cfg_t& mac_cfg)
phr_procedure.set_config(mac_cfg.get_phr_cfg());
sr_procedure.set_config(mac_cfg.get_sr_cfg());
ra_procedure.set_config(mac_cfg.get_rach_cfg());
for (uint32_t i = 0; i < ul_harq.size(); i++) {
ul_harq[i].set_config(mac_cfg.get_harq_cfg());
ul_harq_cfg = mac_cfg.get_harq_cfg();
for (auto& i : ul_harq) {
if (i != nullptr) {
i->set_config(ul_harq_cfg);
}
}
setup_timers(mac_cfg.get_time_alignment_timer());
}
@ -572,7 +585,7 @@ void mac::get_metrics(mac_metrics_t m[SRSLTE_MAX_CARRIERS])
int dl_avg_ret_count = 0;
int ul_avg_ret_count = 0;
for (uint32_t r = 0; r < SRSLTE_MAX_CARRIERS; r++) {
for (uint32_t r = 0; r < dl_harq.size(); r++) {
tx_pkts += metrics[r].tx_pkts;
tx_errors += metrics[r].tx_errors;
tx_brate += metrics[r].tx_brate;
@ -582,7 +595,7 @@ void mac::get_metrics(mac_metrics_t m[SRSLTE_MAX_CARRIERS])
ul_buffer += metrics[r].ul_buffer;
if (metrics[r].rx_pkts) {
dl_avg_ret += dl_harq[r].get_average_retx();
dl_avg_ret += dl_harq.at(r)->get_average_retx();
dl_avg_ret_count++;
}
}
@ -595,7 +608,7 @@ void mac::get_metrics(mac_metrics_t m[SRSLTE_MAX_CARRIERS])
rx_pkts ? ((float)100 * rx_errors / rx_pkts) : 0.0f,
dl_avg_ret,
tx_pkts ? ((float)100 * tx_errors / tx_pkts) : 0.0f,
ul_harq[0].get_average_retx());
ul_harq.at(0)->get_average_retx());
metrics[0].ul_buffer = (int)bsr_procedure.get_buffer_state();
memcpy(m, metrics, sizeof(mac_metrics_t) * SRSLTE_MAX_CARRIERS);

View File

@ -1617,14 +1617,28 @@ bool rrc::con_reconfig(asn1::rrc::rrc_conn_recfg_s* reconfig)
rrc_conn_recfg_v920_ies_s* reconfig_r920 = &reconfig_r890->non_crit_ext;
if (reconfig_r920->non_crit_ext_present) {
rrc_conn_recfg_v1020_ies_s* reconfig_r1020 = &reconfig_r920->non_crit_ext;
// Handle Add/Modify SCell list
if (reconfig_r1020->s_cell_to_add_mod_list_r10_present) {
for (uint32_t i = 0; i < reconfig_r1020->s_cell_to_add_mod_list_r10.size(); i++) {
phy->set_config_scell(&reconfig_r1020->s_cell_to_add_mod_list_r10[i]);
auto scell_config = &reconfig_r1020->s_cell_to_add_mod_list_r10[i];
// Call mac reconfiguration
mac->reconfiguration(scell_config->s_cell_idx_r10, true);
// Call phy reconfiguration
phy->set_config_scell(scell_config);
}
}
// Handle Remove SCell list
if (reconfig_r1020->s_cell_to_release_list_r10_present) {
rrc_log->console("s_cell_to_release_list_r10 not handled\n");
for (uint32_t i = 0; i < reconfig_r1020->s_cell_to_release_list_r10.size(); i++) {
// Call mac reconfiguration
mac->reconfiguration(reconfig_r1020->s_cell_to_release_list_r10[i], false);
// Call phy reconfiguration
// TODO: Implement phy layer cell removal
}
}
}
}